1 /*
2 * Drawing functions.
3 *
4 * This file is part of abcm2ps.
5 *
6 * Copyright (C) 1998-2017 Jean-François Moine
7 * Adapted from abc2ps, Copyright (C) 1996,1997 Michael Methfessel
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18
19 #include "abcm2ps.h"
20
21 struct BEAM { /* packages info on one beam */
22 struct SYMBOL *s1, *s2;
23 float a, b;
24 short nflags;
25 };
26
27 static char *acc_tb[] = { "", "sh", "nt", "ft", "dsh", "dft" };
28
29 /* scaling stuff */
30 static int scale_voice; /* staff (0) or voice(1) scaling */
31 static float cur_scale = 1; /* voice or staff scale */
32 static float cur_trans = 0; /* != 0 when scaled staff */
33 static float cur_staff = 1; /* current scaled staff */
34 static int cur_color = 0; /* current color */
35
36 static void draw_note(float x,
37 struct SYMBOL *s,
38 int fl);
39 static void set_tie_room(void);
40
41 // set the symbol color
42
43
44 /* set the voice color */
set_color(int new_color)45 void set_color(int new_color)
46 {
47 if (new_color == cur_color)
48 return;
49 cur_color = new_color;
50 a2b("%.2f %.2f %.2f setrgbcolor ",
51 (float) (cur_color >> 16) / 255,
52 (float) ((cur_color >> 8) & 0xff) / 255,
53 (float) (cur_color & 0xff) / 255);
54 }
55
56 /* output debug annotations */
anno_out(struct SYMBOL * s,char type)57 static void anno_out(struct SYMBOL *s, char type)
58 {
59 if (s->linenum == 0)
60 return;
61 if (mbf[-1] != '\n')
62 *mbf++ = '\n';
63 a2b("%%A %c %d %d ", type, s->linenum, s->colnum);
64 putxy(s->x - s->wl - 2, staff_tb[s->staff].y + s->ymn - 2);
65 if (type != 'b' && type != 'e') /* if not beam */
66 a2b("%.1f %d", s->wl + s->wr + 4, s->ymx - s->ymn + 4);
67 a2b("\n");
68 }
69
70 /* -- up/down shift needed to get k*6 -- */
rnd6(float y)71 static float rnd6(float y)
72 {
73 int iy;
74
75 iy = ((int) (y + 2.999) + 12) / 6 * 6 - 12;
76 return iy - y;
77 }
78
79 /* -- compute the best vertical offset for the beams -- */
b_pos(int grace,int stem,int flags,float b)80 static float b_pos(int grace,
81 int stem,
82 int flags,
83 float b)
84 {
85 float d1, d2, shift, depth;
86 float top, bot;
87
88 shift = !grace ? BEAM_SHIFT : 3.5;
89 depth = !grace ? BEAM_DEPTH : 1.8;
90 if (stem > 0) {
91 bot = b - (flags - 1) * shift - depth;
92 if (bot > 26)
93 return 0;
94 top = b;
95 } else {
96 top = b + (flags - 1) * shift + depth;
97 if (top < -2)
98 return 0;
99 bot = b;
100 }
101
102 d1 = rnd6(top - BEAM_OFFSET);
103 d2 = rnd6(bot + BEAM_OFFSET);
104 if (d1 * d1 > d2 * d2)
105 return d2;
106 return d1;
107 }
108
109 /* duplicate a note for beaming continuation */
sym_dup(struct SYMBOL * s_orig)110 static struct SYMBOL *sym_dup(struct SYMBOL *s_orig)
111 {
112 struct SYMBOL *s;
113 int m;
114
115 s = (struct SYMBOL *) getarena(sizeof *s);
116 memcpy(s, s_orig, sizeof *s);
117 s->flags |= ABC_F_INVIS;
118 s->text = NULL;
119 for (m = 0; m <= s->nhd; m++)
120 s->u.note.notes[m].sl1 = 0;
121 memset(&s->u.note.dc, 0, sizeof s->u.note.dc);
122
123 s->gch = NULL;
124 s->ly = NULL;
125 return s;
126 }
127
128 /* -- calculate a beam -- */
129 /* (the staves may be defined or not) */
calculate_beam(struct BEAM * bm,struct SYMBOL * s1)130 static int calculate_beam(struct BEAM *bm,
131 struct SYMBOL *s1)
132 {
133 struct SYMBOL *s, *s2;
134 int notes, nflags, staff, voice, two_staves, two_dir, visible = 0;
135 float x, y, ys, a, b, max_stem_err;
136 float sx, sy, sxx, sxy, syy, a0, stem_xoff, scale;
137 static float min_tb[2][6] = {
138 {STEM_MIN, STEM_MIN,
139 STEM_MIN2, STEM_MIN3, STEM_MIN4, STEM_MIN4},
140 {STEM_CH_MIN, STEM_CH_MIN,
141 STEM_CH_MIN2, STEM_CH_MIN3, STEM_CH_MIN4, STEM_CH_MIN4}
142 };
143
144 if (!(s1->sflags & S_BEAM_ST)) { /* beam from previous music line */
145 s = sym_dup(s1);
146 s->prev = s1->prev;
147 if (s->prev)
148 s->prev->next = s;
149 else
150 voice_tb[s->voice].sym = s;
151 s1->prev = s;
152 s->next = s1;
153 s->ts_prev = s1->ts_prev;
154 // if (s->ts_prev)
155 s->ts_prev->ts_next = s;
156 s1->ts_prev = s;
157 s->ts_next = s1;
158 for (s2 = s->ts_prev; /*s2*/; s2 = s2->ts_prev) {
159 switch (s2->type) {
160 default:
161 continue;
162 case CLEF:
163 case KEYSIG:
164 case TIMESIG:
165 break;
166 }
167 break;
168 }
169 s->x -= 12;
170 if (s->x > s2->x + 12)
171 s->x = s2->x + 12;
172 s->sflags &= S_SEQST;
173 s->sflags |= S_BEAM_ST | S_TEMP;
174 s->u.note.slur_st = 0;
175 s->u.note.slur_end = 0;
176 s1 = s;
177 }
178
179 /* search last note in beam */
180 notes = nflags = 0; /* set x positions, count notes and flags */
181 two_staves = two_dir = 0;
182 staff = s1->staff;
183 voice = s1->voice;
184 stem_xoff = (s1->flags & ABC_F_GRACE) ? GSTEM_XOFF : s1->u.note.sdx;
185 for (s2 = s1; ; s2 = s2->next) {
186 if (s2->abc_type == ABC_T_NOTE) {
187 if (s2->nflags > nflags)
188 nflags = s2->nflags;
189 notes++;
190 if (s2->staff != staff)
191 two_staves = 1;
192 if (s2->stem != s1->stem)
193 two_dir = 1;
194 if (!visible
195 && !(s2->flags & ABC_F_INVIS)
196 && (!(s2->flags & ABC_F_STEMLESS)
197 || (s2->sflags & S_TREM2)))
198 visible = 1;
199 if (s2->sflags & S_BEAM_END)
200 break;
201 }
202 if (!s2->next) { /* beam towards next music line */
203 for (; ; s2 = s2->prev) {
204 if (s2->abc_type == ABC_T_NOTE)
205 break;
206 }
207 s = sym_dup(s2);
208 s->next = s2->next;
209 if (s->next)
210 s->next->prev = s;
211 s2->next = s;
212 s->prev = s2;
213 s->ts_next = s2->ts_next;
214 if (s->ts_next)
215 s->ts_next->ts_prev = s;
216 s2->ts_next = s;
217 s->ts_prev = s2;
218 s->sflags &= S_SEQST;
219 s->sflags |= S_BEAM_END | S_TEMP;
220 s->u.note.slur_st = 0;
221 s->u.note.slur_end = 0;
222 s->x += 12;
223 if (s->x < realwidth - 12)
224 s->x = realwidth - 12;
225 s2 = s;
226 notes++;
227 break;
228 }
229 }
230 if (!visible)
231 return 0;
232
233 bm->s2 = s2; /* (don't display the flags) */
234 if (staff_tb[staff].y == 0) { /* staves not defined */
235 if (two_staves)
236 return 0;
237 } else { /* staves defined */
238 if (!two_staves) {
239 bm->s1 = s1; /* beam already calculated */
240 if (s1->xs == s2->xs)
241 bug("beam with null length", 1);
242 bm->a = (s1->ys- s2->ys) / (s1->xs - s2->xs);
243 bm->b = s1->ys - s1->xs * bm->a
244 + staff_tb[staff].y;
245 bm->nflags = nflags;
246 return 1;
247 }
248 }
249
250 sx = sy = sxx = sxy = syy = 0; /* linear fit through stem ends */
251 for (s = s1; ; s = s->next) {
252 if (s->abc_type != ABC_T_NOTE)
253 continue;
254 if ((scale = voice_tb[s->voice].scale) == 1)
255 scale = staff_tb[s->staff].staffscale;
256 if (s->stem >= 0)
257 x = stem_xoff + s->u.note.notes[0].shhd;
258 else
259 x = -stem_xoff + s->u.note.notes[s->nhd].shhd;
260 x *= scale;
261 x += s->x;
262 s->xs = x;
263 y = s->ys + staff_tb[s->staff].y;
264 sx += x; sy += y;
265 sxx += x * x; sxy += x * y; syy += y * y;
266 if (s == s2)
267 break;
268 }
269
270 /* beam fct: y=ax+b */
271 a = (sxy * notes - sx * sy) / (sxx * notes - sx * sx);
272 b = (sy - a * sx) / notes;
273
274 /* the next few lines modify the slope of the beam */
275 if (!(s1->flags & ABC_F_GRACE)) {
276 if (notes >= 3) {
277 float hh;
278
279 hh = syy - a * sxy - b * sy; /* flatten if notes not in line */
280 if (hh > 0
281 && hh / (notes - 2) > .5)
282 a *= BEAM_FLATFAC;
283 }
284 if (a >= 0)
285 a = BEAM_SLOPE * a / (BEAM_SLOPE + a); /* max steepness for beam */
286 else
287 a = BEAM_SLOPE * a / (BEAM_SLOPE - a);
288 } else {
289 if (a > BEAM_SLOPE)
290 a = BEAM_SLOPE;
291 else if (a < -BEAM_SLOPE)
292 a = -BEAM_SLOPE;
293 }
294
295 /* to decide if to draw flat etc. use normalized slope a0 */
296 a0 = a * (s2->xs - s1->xs) / (20 * (notes - 1));
297
298 if (a0 * a0 < BEAM_THRESH * BEAM_THRESH)
299 a = 0; /* flat below threshhold */
300
301 b = (sy - a * sx) / notes; /* recalculate b for new slope */
302
303 /* if (nflags>1) b=b+2*stem;*/ /* leave a bit more room if several beams */
304
305 /* have flat beams when asked */
306 if (cfmt.flatbeams) {
307 if (!(s1->flags & ABC_F_GRACE))
308 b = -11 + staff_tb[staff].y;
309 else
310 b = 35 + staff_tb[staff].y;
311 a = 0;
312 }
313
314 /*fixme: have a look again*/
315 /* have room for the symbols in the staff */
316 max_stem_err = 0; /* check stem lengths */
317 s = s1;
318 if (two_dir) { /* 2 directions */
319 /*fixme: more to do*/
320 if (!(s1->flags & ABC_F_GRACE))
321 ys = BEAM_SHIFT;
322 else
323 ys = 3.5;
324 ys *= (nflags - 1);
325 ys += BEAM_DEPTH;
326 ys *= .5;
327 if (s1->stem != s2->stem && s1->nflags < s2->nflags)
328 ys *= s2->stem;
329 else
330 ys *= s1->stem;
331 b += ys;
332 } else if (!(s1->flags & ABC_F_GRACE)) { /* normal notes */
333 float stem_err, beam_h;
334
335 beam_h = BEAM_DEPTH + BEAM_SHIFT * (nflags - 1);
336 while (s->ts_prev->abc_type == ABC_T_NOTE
337 && s->ts_prev->time == s->time
338 && s->ts_prev->x > s1->xs)
339 s = s->ts_prev;
340
341 for (; s && s->time <= s2->time; s = s->ts_next) {
342 if (s->abc_type != ABC_T_NOTE
343 || (s->flags & ABC_F_INVIS)
344 || (s->staff != staff
345 && s->voice != voice)) {
346 continue;
347 }
348 x = s->voice == voice ? s->xs : s->x;
349 ys = a * x + b - staff_tb[s->staff].y;
350 if (s->voice == voice) {
351 if (s->nhd == 0)
352 stem_err = min_tb[0][(unsigned) s->nflags];
353 else
354 stem_err = min_tb[1][(unsigned) s->nflags];
355 if (s->stem > 0) {
356 if (s->pits[s->nhd] > 26) {
357 stem_err -= 2;
358 if (s->pits[s->nhd] > 28)
359 stem_err -= 2;
360 }
361 stem_err -= ys - (float) (3 *
362 (s->pits[s->nhd] - 18));
363 } else {
364 if (s->pits[0] < 18) {
365 stem_err -= 2;
366 if (s->pits[0] < 16)
367 stem_err -= 2;
368 }
369 stem_err -= (float) (3 *
370 (s->pits[0] - 18)) - ys;
371 }
372 stem_err += BEAM_DEPTH + BEAM_SHIFT * (s->nflags - 1);
373 } else {
374 /*fixme: KO when two_staves*/
375 if (s1->stem > 0) {
376 if (s->stem > 0) {
377 /*fixme: KO when the voice numbers are inverted*/
378 if (s->ymn > ys + 4
379 || s->ymx < ys - beam_h - 2)
380 continue;
381 if (s->voice > voice)
382 stem_err = s->ymx - ys;
383 else
384 stem_err = s->ymn + 8 - ys;
385 } else {
386 stem_err = s->ymx - ys;
387 }
388 } else {
389 if (s->stem < 0) {
390 if (s->ymx < ys - 4
391 || s->ymn > ys - beam_h - 2)
392 continue;
393 if (s->voice < voice)
394 stem_err = ys - s->ymn;
395 else
396 stem_err = ys - s->ymx + 8;
397 } else {
398 stem_err = ys - s->ymn;
399 }
400 }
401 stem_err += 2 + beam_h;
402 }
403 if (stem_err > max_stem_err)
404 max_stem_err = stem_err;
405 }
406 } else { /* grace notes */
407 for ( ; ; s = s->next) {
408 float stem_err;
409
410 ys = a * s->xs + b - staff_tb[s->staff].y;
411 stem_err = GSTEM - 2;
412 if (s->stem > 0)
413 stem_err -= ys - (float) (3 *
414 (s->pits[s->nhd] - 18));
415 else
416 stem_err += ys - (float) (3 *
417 (s->pits[0] - 18));
418 stem_err += 3 * (s->nflags - 1);
419 if (stem_err > max_stem_err)
420 max_stem_err = stem_err;
421 if (s == s2)
422 break;
423 }
424 }
425
426 if (max_stem_err > 0) /* shift beam if stems too short */
427 b += s1->stem * max_stem_err;
428
429 /* have room for the gracenotes, bars and clefs */
430 /*fixme: test*/
431 if (!two_staves && !two_dir)
432 for (s = s1->next; ; s = s->next) {
433 struct SYMBOL *g;
434
435 switch (s->type) {
436 case NOTEREST: /* cannot move rests in multi-voices */
437 if (s->abc_type != ABC_T_REST)
438 break;
439 g = s->ts_next;
440 if (!g || g->staff != staff
441 || g->type != NOTEREST)
442 break;
443 //fixme:too much vertical shift if some space above the note
444 //fixme:this does not fix rest under beam in second voice (ts_prev)
445 /*fall thru*/
446 case BAR:
447 #if 1
448 if (s->flags & ABC_F_INVIS)
449 #else
450 //??
451 if (!(s->flags & ABC_F_INVIS))
452 #endif
453 break;
454 /*fall thru*/
455 case CLEF:
456 y = a * s->x + b;
457 if (s1->stem > 0) {
458 y = s->ymx - y
459 + BEAM_DEPTH + BEAM_SHIFT * (nflags - 1)
460 + 2;
461 if (y > 0)
462 b += y;
463 } else {
464 y = s->ymn - y
465 - BEAM_DEPTH - BEAM_SHIFT * (nflags - 1)
466 - 2;
467 if (y < 0)
468 b += y;
469 }
470 break;
471 case GRACE:
472 g = s->extra;
473 for ( ; g; g = g->next) {
474 if (g->type != NOTEREST)
475 continue;
476 y = a * g->x + b;
477 if (s1->stem > 0) {
478 y = g->ymx - y
479 + BEAM_DEPTH + BEAM_SHIFT * (nflags - 1)
480 + 2;
481 if (y > 0)
482 b += y;
483 } else {
484 y = g->ymn - y
485 - BEAM_DEPTH - BEAM_SHIFT * (nflags - 1)
486 - 2;
487 if (y < 0)
488 b += y;
489 }
490 }
491 break;
492 }
493 if (s == s2)
494 break;
495 }
496
497 if (a == 0) /* shift flat beams onto staff lines */
498 b += b_pos(s1->flags & ABC_F_GRACE, s1->stem, nflags,
499 b - staff_tb[staff].y);
500
501 /* adjust final stems and rests under beam */
502 for (s = s1; ; s = s->next) {
503 float dy;
504
505 switch (s->abc_type) {
506 case ABC_T_NOTE:
507 s->ys = a * s->xs + b - staff_tb[s->staff].y;
508 if (s->stem > 0) {
509 s->ymx = s->ys + 2.5;
510 #if 0
511 //fixme: hack
512 if (s->ts_prev
513 && s->ts_prev->stem > 0
514 && s->ts_prev->staff == s->staff
515 && s->ts_prev->ymn < s->ymx
516 && s->ts_prev->x == s->x
517 && s->u.note.notes[0].shhd == 0) {
518 s->ts_prev->x -= 5; /* fix stem clash */
519 s->ts_prev->xs -= 5;
520 }
521 #endif
522 } else {
523 s->ymn = s->ys - 2.5;
524 }
525 break;
526 case ABC_T_REST:
527 y = a * s->x + b - staff_tb[s->staff].y;
528 dy = BEAM_DEPTH + BEAM_SHIFT * (nflags - 1)
529 + (s->head != H_FULL ? 4 : 9);
530 if (s1->stem > 0) {
531 y -= dy;
532 if (s1->multi == 0 && y > 12)
533 y = 12;
534 if (s->y <= y)
535 break;
536 } else {
537 y += dy;
538 if (s1->multi == 0 && y < 12)
539 y = 12;
540 if (s->y >= y)
541 break;
542 }
543 if (s->head != H_FULL) {
544 int iy;
545
546 iy = ((int) y + 3 + 12) / 6 * 6 - 12;
547 y = iy;
548 }
549 s->y = y;
550 break;
551 }
552 if (s == s2)
553 break;
554 }
555
556 /* save beam parameters */
557 if (staff_tb[staff].y == 0) /* if staves not defined */
558 return 0;
559 bm->s1 = s1;
560 bm->a = a;
561 bm->b = b;
562 bm->nflags = nflags;
563 return 1;
564 }
565
566 /* -- draw a single beam -- */
567 /* (the staves are defined) */
draw_beam(float x1,float x2,float dy,float h,struct BEAM * bm,int n)568 static void draw_beam(float x1,
569 float x2,
570 float dy,
571 float h,
572 struct BEAM *bm,
573 int n) /* beam number (1..n) */
574 {
575 struct SYMBOL *s;
576 float y1, dy2;
577
578 s = bm->s1;
579 if ((s->sflags & S_TREM2) && n > s->nflags - s->aux
580 && s->head != H_EMPTY) {
581 if (s->head >= H_OVAL) {
582 x1 = s->x + 6;
583 x2 = bm->s2->x - 6;
584 } else {
585 x1 += 5;
586 x2 -= 6;
587 }
588 }
589
590 y1 = bm->a * x1 + bm->b - dy;
591 x2 -= x1;
592 dy2 = bm->a * x2;
593
594 putf(h);
595 putx(x2);
596 putf(dy2);
597 putxy(x1, y1);
598 a2b("bm\n");
599 }
600
601 /* -- draw the beams for one word -- */
602 /* (the staves are defined) */
draw_beams(struct BEAM * bm)603 static void draw_beams(struct BEAM *bm)
604 {
605 struct SYMBOL *s, *s1, *s2;
606 int i, beam_dir;
607 float shift, bshift, bstub, bh, da;
608
609 s1 = bm->s1;
610 /*fixme: KO if many staves with different scales*/
611 //fixme: useless?
612 // set_scale(s1);
613 s2 = bm->s2;
614 if (!(s1->flags & ABC_F_GRACE)) {
615 bshift = BEAM_SHIFT;
616 bstub = BEAM_STUB;
617 shift = .34; /* (half width of the stem) */
618 bh = BEAM_DEPTH;
619 } else {
620 bshift = 3.5;
621 bstub = 3.2;
622 shift = .29;
623 bh = 1.8;
624 }
625
626 /*fixme: quick hack for stubs at end of beam and different stem directions*/
627 beam_dir = s1->stem;
628 if (s1->stem != s2->stem
629 && s1->nflags < s2->nflags)
630 beam_dir = s2->stem;
631 if (beam_dir < 0)
632 bh = -bh;
633 if (cur_trans == 0 && cur_scale != 1) {
634 bm->a /= cur_scale;
635 bm->b = s1->ys - s1->xs * bm->a
636 + staff_tb[s1->staff].y;
637 bshift *= cur_scale;
638 }
639
640 /* make first beam over whole word and adjust the stem lengths */
641 draw_beam(s1->xs - shift, s2->xs + shift, 0., bh, bm, 1);
642 da = 0;
643 for (s = s1; ; s = s->next) {
644 if (s->abc_type == ABC_T_NOTE
645 && s->stem != beam_dir)
646 s->ys = bm->a * s->xs + bm->b
647 - staff_tb[s->staff].y
648 + bshift * (s->nflags - 1) * s->stem
649 - bh;
650 if (s == s2)
651 break;
652 }
653
654 if (s1->sflags & S_FEATHERED_BEAM) {
655 da = bshift / (s2->xs - s1->xs);
656 if (s1->dur > s2->dur) {
657 da = -da;
658 bshift = da * s1->xs;
659 } else {
660 bshift = da * s2->xs;
661 }
662 da = da * beam_dir;
663 }
664
665 /* other beams with two or more flags */
666 shift = 0;
667 for (i = 2; i <= bm->nflags; i++) {
668 shift += bshift;
669 if (da != 0)
670 bm->a += da;
671 for (s = s1; ; s = s->next) {
672 struct SYMBOL *k1, *k2;
673 float x1;
674
675 if (s->abc_type != ABC_T_NOTE
676 || s->nflags < i) {
677 if (s == s2)
678 break;
679 continue;
680 }
681 if ((s->sflags & S_TREM1)
682 && i > s->nflags - s->aux) {
683 if (s->head >= H_OVAL)
684 x1 = s->x;
685 else
686 x1 = s->xs;
687 draw_beam(x1 - 5, x1 + 5,
688 (shift + 2.5) * beam_dir,
689 bh, bm, i);
690 if (s == s2)
691 break;
692 continue;
693 }
694 k1 = s;
695 for (;;) {
696 if (s == s2)
697 break;
698 if (s->next->type == NOTEREST) {
699 if (s->next->sflags & S_TREM1) {
700 if (s->next->nflags - s->next->aux < i)
701 break;
702 } else if (s->next->nflags < i) {
703 break;
704 }
705 }
706 if ((s->next->sflags & S_BEAM_BR1)
707 || ((s->next->sflags & S_BEAM_BR2) && i > 2))
708 break;
709 s = s->next;
710 }
711 k2 = s;
712 while (k2->abc_type != ABC_T_NOTE)
713 k2 = k2->prev;
714 x1 = k1->xs;
715 if (k1 == k2) {
716 if (k1 == s1) {
717 x1 += bstub;
718 } else if (k1 == s2) {
719 x1 -= bstub;
720 } else if ((k1->sflags & S_BEAM_BR1)
721 || ((k1->sflags & S_BEAM_BR2)
722 && i > 2)) {
723 x1 += bstub;
724 } else {
725 struct SYMBOL *k;
726
727 k = k1->next;
728 while (k->abc_type != ABC_T_NOTE)
729 k = k->next;
730 if ((k->sflags & S_BEAM_BR1)
731 || ((k->sflags & S_BEAM_BR2)
732 && i > 2)) {
733 x1 -= bstub;
734 } else {
735 k1 = k1->prev;
736 while (k1->abc_type != ABC_T_NOTE)
737 k1 = k1->prev;
738 if (k1->nflags < k->nflags
739 || (k1->nflags == k->nflags
740 && k1->dots < k->dots))
741 x1 += bstub;
742 else
743 x1 -= bstub;
744 }
745 }
746 }
747 draw_beam(x1, k2->xs,
748 #if 1
749 shift * beam_dir,
750 #else
751 shift * k1->stem, /*fixme: more complicated */
752 #endif
753 bh, bm, i);
754 if (s == s2)
755 break;
756 }
757 }
758 if (s1->sflags & S_TEMP)
759 unlksym(s1);
760 else if (s2->sflags & S_TEMP)
761 unlksym(s2);
762 }
763
764 /* -- draw a system brace or bracket -- */
draw_sysbra(float x,int staff,int flag)765 static void draw_sysbra(float x, int staff, int flag)
766 {
767 int i, end;
768 float yt, yb;
769
770 while (cursys->staff[staff].empty) {
771 // || staff_tb[staff].stafflines == 0) {
772 if (cursys->staff[staff].flags & flag)
773 return;
774 staff++;
775 }
776 i = end = staff;
777 for (;;) {
778 if (!cursys->staff[i].empty)
779 // && staff_tb[i].stafflines != 0)
780 end = i;
781 if (cursys->staff[i].flags & flag)
782 break;
783 i++;
784 }
785 yt = staff_tb[staff].y + staff_tb[staff].topbar
786 * staff_tb[staff].staffscale;
787 yb = staff_tb[end].y + staff_tb[end].botbar
788 * staff_tb[end].staffscale;
789 a2b("%.1f %.1f %.1f %s\n",
790 yt - yb, x, yt,
791 (flag & (CLOSE_BRACE | CLOSE_BRACE2)) ? "brace" : "bracket");
792 }
793
794 /* -- draw the left side of the staves -- */
draw_lstaff(float x)795 static void draw_lstaff(float x)
796 {
797 int i, j, l, nst;
798 float yb;
799
800 if (cfmt.alignbars)
801 return;
802 nst = cursys->nstaff;
803 l = 0;
804 for (i = 0; ; i++) {
805 if (cursys->staff[i].flags & (OPEN_BRACE | OPEN_BRACKET))
806 l++;
807 if (!cursys->staff[i].empty)
808 // && staff_tb[i].stafflines != 0)
809 break;
810 if (cursys->staff[i].flags & (CLOSE_BRACE | CLOSE_BRACKET))
811 l--;
812 if (i == nst)
813 break;
814 }
815 for (j = nst; j > i; j--) {
816 if (!cursys->staff[j].empty)
817 // && staff_tb[j].stafflines != 0)
818 break;
819 }
820 if (i == j && l == 0)
821 return;
822 set_sscale(-1);
823 yb = staff_tb[j].y + staff_tb[j].botbar
824 * staff_tb[j].staffscale;
825 a2b("%.1f %.1f %.1f bar\n",
826 staff_tb[i].y + staff_tb[i].topbar * staff_tb[i].staffscale - yb,
827 x, yb);
828 for (i = 0; i <= nst; i++) {
829 if (cursys->staff[i].flags & OPEN_BRACE)
830 draw_sysbra(x, i, CLOSE_BRACE);
831 if (cursys->staff[i].flags & OPEN_BRACKET)
832 draw_sysbra(x, i, CLOSE_BRACKET);
833 if (cursys->staff[i].flags & OPEN_BRACE2)
834 draw_sysbra(x - 6, i, CLOSE_BRACE2);
835 if (cursys->staff[i].flags & OPEN_BRACKET2)
836 draw_sysbra(x - 6, i, CLOSE_BRACKET2);
837 }
838 }
839
840 /* -- draw a staff -- */
draw_staff(int staff,float x1,float x2)841 static void draw_staff(int staff,
842 float x1, float x2)
843 {
844 char *stafflines;
845 int i, l, thick = -1;
846 float y, w;
847
848 /* draw the staff */
849 set_sscale(staff);
850 y = staff_tb[staff].y;
851 stafflines = staff_tb[staff].stafflines;
852 l = strlen(stafflines);
853 for (i = 0; i < l; i++) {
854 if (stafflines[i] != '.') {
855 w = x2 - x1;
856 for ( ; i < l; i++) {
857 if (stafflines[i] != '.') {
858 if (stafflines[i] != '|') {
859 if (thick != 1) {
860 if (thick >= 0)
861 a2b("stroke\n");
862 a2b("1.5 SLW ");
863 thick = 1;
864 }
865 } else {
866 if (thick != 0) {
867 if (thick >= 0)
868 a2b("stroke\n");
869 a2b("dlw ");
870 thick = 0;
871 }
872 }
873 putx(w);
874 putxy(x1, y);
875 a2b("M 0 RL ");
876 }
877 y += 6;
878 }
879 a2b("stroke\n");
880 break;
881 }
882 y += 6;
883 }
884 }
885
886 /* -- draw the time signature -- */
draw_timesig(float x,struct SYMBOL * s)887 static void draw_timesig(float x,
888 struct SYMBOL *s)
889 {
890 unsigned i, staff, l, l2;
891 char *f, meter[64];
892 float dx, y;
893
894 if (s->u.meter.nmeter == 0)
895 return;
896 staff = s->staff;
897 x -= s->wl;
898 y = staff_tb[staff].y;
899 for (i = 0; i < s->u.meter.nmeter; i++) {
900 l = strlen(s->u.meter.meter[i].top);
901 if (l > sizeof s->u.meter.meter[i].top)
902 l = sizeof s->u.meter.meter[i].top;
903 if (s->u.meter.meter[i].bot[0] != '\0') {
904 sprintf(meter, "(%.8s)(%.2s)",
905 s->u.meter.meter[i].top,
906 s->u.meter.meter[i].bot);
907 f = "tsig";
908 l2 = strlen(s->u.meter.meter[i].bot);
909 if (l2 > sizeof s->u.meter.meter[i].bot)
910 l2 = sizeof s->u.meter.meter[i].bot;
911 if (l2 > l)
912 l = l2;
913 } else switch (s->u.meter.meter[i].top[0]) {
914 case 'C':
915 if (s->u.meter.meter[i].top[1] != '|') {
916 f = "csig";
917 } else {
918 f = "ctsig";
919 l--;
920 }
921 meter[0] = '\0';
922 x -= 5;
923 y += 12;
924 break;
925 case 'c':
926 if (s->u.meter.meter[i].top[1] != '.') {
927 f = "imsig";
928 } else {
929 f = "iMsig";
930 l--;
931 }
932 meter[0] = '\0';
933 break;
934 case 'o':
935 if (s->u.meter.meter[i].top[1] != '.') {
936 f = "pmsig";
937 } else {
938 f = "pMsig";
939 l--;
940 }
941 meter[0] = '\0';
942 break;
943 case '(':
944 case ')':
945 sprintf(meter, "(\\%s)",
946 s->u.meter.meter[i].top);
947 f = "stsig";
948 break;
949 default:
950 sprintf(meter, "(%.8s)",
951 s->u.meter.meter[i].top);
952 f = "stsig";
953 break;
954 }
955 if (meter[0] != '\0')
956 a2b("%s ", meter);
957 dx = (float) (13 * l);
958 putxy(x + dx * .5, y);
959 a2b("%s\n", f);
960 x += dx;
961 }
962 }
963
964 /* -- draw an accidental -- */
draw_acc(int acc,int microscale)965 static void draw_acc(int acc, int microscale)
966 {
967 int n, d;
968
969 n = parse.micro_tb[acc >> 3];
970 if (acc >> 3 != 0 && microscale) {
971 if (microscale) {
972 d = microscale;
973 n = acc >> 3;
974 } else {
975 d = ((n & 0xff) + 1) * 2;
976 n = (n >> 8) + 1;
977 }
978 a2b("%d %s%d ", n, acc_tb[acc & 0x07], d);
979 } else {
980 a2b("%s%d ", acc_tb[acc & 0x07], n);
981 }
982 }
983
984 // draw helper lines
draw_hl(float x,float staffb,int up,int y,char * stafflines,char * hltype)985 static void draw_hl(float x, float staffb, int up,
986 int y, char *stafflines, char *hltype)
987 {
988 int i, l;
989
990 l = strlen(stafflines);
991
992 // lower ledger lines
993 if (!up) {
994 for (i = 0; i < l - 1; i++) {
995 if (stafflines[i] != '.')
996 break;
997 }
998 i = i * 6 - 6;
999 for ( ; i >= y; i -= 6) {
1000 putxy(x, staffb + i);
1001 a2b("%s ", hltype);
1002 }
1003 return;
1004 }
1005
1006 // upper ledger lines
1007 i = l * 6;
1008 for ( ; i <= y; i += 6) {
1009 putxy(x, staffb + i);
1010 a2b("%s ", hltype);
1011 }
1012 }
1013
1014 /* -- draw a key signature -- */
draw_keysig(struct VOICE_S * p_voice,float x,struct SYMBOL * s)1015 static void draw_keysig(struct VOICE_S *p_voice,
1016 float x,
1017 struct SYMBOL *s)
1018 {
1019 int old_sf = s->aux;
1020 int staff = p_voice->staff;
1021 float staffb = staff_tb[staff].y;
1022 int i, clef_ix, shift;
1023 const signed char *p_seq;
1024
1025 static const char sharp_cl[] = {24, 9, 15, 21, 6, 12, 18};
1026 static const char flat_cl[] = {12, 18, 24, 9, 15, 21, 6};
1027 // (the ending 0 is needed to avoid array overflow)
1028 static const signed char sharp1[] = {-9, 12, -9, -9, 12, -9, 0};
1029 static const signed char sharp2[] = {12, -9, 12, -9, 12, -9, 0};
1030 static const signed char flat1[] = {9, -12, 9, -12, 9, -12, 0};
1031 static const signed char flat2[] = {-12, 9, -12, 9, -12, 9, 0};
1032
1033 clef_ix = s->u.key.clef_delta;
1034 if (clef_ix & 1)
1035 clef_ix += 7;
1036 clef_ix /= 2;
1037 while (clef_ix < 0)
1038 clef_ix += 7;
1039 clef_ix %= 7;
1040
1041 /* normal accidentals */
1042 if (s->u.key.nacc == 0 && !s->u.key.empty) {
1043
1044 /* put neutrals if 'accidental cancel' */
1045 if (cfmt.cancelkey || s->u.key.sf == 0) {
1046
1047 /* when flats to sharps, or sharps to flats, */
1048 if (s->u.key.sf == 0
1049 || old_sf * s->u.key.sf < 0) {
1050
1051 /* old sharps */
1052 shift = sharp_cl[clef_ix];
1053 p_seq = shift > 9 ? sharp1 : sharp2;
1054 for (i = 0; i < old_sf; i++) {
1055 putxy(x, staffb + shift);
1056 a2b("nt0 ");
1057 shift += *p_seq++;
1058 x += 5.5;
1059 }
1060
1061 /* old flats */
1062 shift = flat_cl[clef_ix];
1063 p_seq = shift < 18 ? flat1 : flat2;
1064 for (i = 0; i > old_sf; i--) {
1065 putxy(x, staffb + shift);
1066 a2b("nt0 ");
1067 shift += *p_seq++;
1068 x += 5.5;
1069 }
1070 if (s->u.key.sf != 0)
1071 x += 3; /* extra space */
1072 }
1073 }
1074
1075 /* new sharps */
1076 if (s->u.key.sf > 0) {
1077 shift = sharp_cl[clef_ix];
1078 p_seq = shift > 9 ? sharp1 : sharp2;
1079 for (i = 0; i < s->u.key.sf; i++) {
1080 putxy(x, staffb + shift);
1081 a2b("sh0 ");
1082 shift += *p_seq++;
1083 x += 5.5;
1084 }
1085 if (cfmt.cancelkey && s->u.key.sf < old_sf) {
1086 x += 2;
1087 for (; i < old_sf; i++) {
1088 putxy(x, staffb + shift);
1089 a2b("nt0 ");
1090 shift += *p_seq++;
1091 x += 5.5;
1092 }
1093 }
1094 }
1095
1096 /* new flats */
1097 if (s->u.key.sf < 0) {
1098 shift = flat_cl[clef_ix];
1099 p_seq = shift < 18 ? flat1 : flat2;
1100 for (i = 0; i > s->u.key.sf; i--) {
1101 putxy(x, staffb + shift);
1102 a2b("ft0 ");
1103 shift += *p_seq++;
1104 x += 5.5;
1105 }
1106 if (cfmt.cancelkey && s->u.key.sf > old_sf) {
1107 x += 2;
1108 for (; i > old_sf; i--) {
1109 putxy(x, staffb + shift);
1110 a2b("nt0 ");
1111 shift += *p_seq++;
1112 x += 5.5;
1113 }
1114 }
1115 }
1116 } else {
1117 int acc, last_acc, last_shift;
1118
1119 /* explicit accidentals */
1120 last_acc = s->u.key.accs[0];
1121 last_shift = 100;
1122 for (i = 0; i < s->u.key.nacc; i++) {
1123 acc = s->u.key.accs[i];
1124 shift = s->u.key.clef_delta * 3 // clef shift
1125 + 3 * (s->u.key.pits[i] - 18);
1126 if (i != 0
1127 && (shift > last_shift + 18
1128 || shift < last_shift - 18))
1129 x -= 5.5; // no clash
1130 else if (acc != last_acc)
1131 x += 3;
1132 last_acc = acc;
1133 if (shift < 0)
1134 draw_hl(x, staffb, 0,
1135 shift, /* lower ledger line */
1136 staff_tb[s->staff].stafflines, "hl");
1137 else if (shift > 24)
1138 draw_hl(x, staffb, 1,
1139 shift, /* upper ledger line */
1140 staff_tb[s->staff].stafflines, "hl");
1141 last_shift = shift;
1142 putxy(x, staffb + shift);
1143 draw_acc(acc, s->u.key.microscale);
1144 x += 5.5;
1145 }
1146 }
1147 if (old_sf != 0 || s->u.key.sf != 0 || s->u.key.nacc != 0)
1148 a2b("\n");
1149 }
1150
1151 /* -- convert the standard measure bars -- */
bar_cnv(int bar_type)1152 static int bar_cnv(int bar_type)
1153 {
1154 switch (bar_type) {
1155 case B_OBRA:
1156 /* case B_CBRA: */
1157 case (B_OBRA << 4) + B_CBRA:
1158 return 0; /* invisible */
1159 // case B_COL:
1160 // return B_BAR; /* dotted */
1161 #if 0
1162 case (B_CBRA << 4) + B_BAR:
1163 return B_BAR;
1164 #endif
1165 case (B_SINGLE << 8) | B_LREP:
1166 case (B_BAR << 4) + B_COL:
1167 bar_type |= (B_OBRA << 8); /* ||: and |: -> [|: */
1168 break;
1169 case (B_BAR << 8) + (B_COL << 4) + B_COL:
1170 bar_type |= (B_OBRA << 12); /* |:: -> [|:: */
1171 break;
1172 case (B_BAR << 12) + (B_COL << 8) + (B_COL << 4) + B_COL:
1173 bar_type |= (B_OBRA << 16); /* |::: -> [|::: */
1174 break;
1175 case (B_COL << 4) + B_BAR:
1176 case (B_COL << 8) + (B_COL << 4) + B_BAR:
1177 case (B_COL << 12) + (B_COL << 8) + (B_COL << 4) + B_BAR:
1178 bar_type <<= 4;
1179 bar_type |= B_CBRA; /* :..| -> :..|] */
1180 break;
1181 case (B_COL << 4) + B_COL:
1182 bar_type = cfmt.dblrepbar; /* :: -> dble repeat bar */
1183 break;
1184 }
1185 return bar_type;
1186 }
1187
1188 /* -- draw a measure bar -- */
draw_bar(struct SYMBOL * s,float bot,float h)1189 static void draw_bar(struct SYMBOL *s, float bot, float h)
1190 {
1191 int staff, bar_type;
1192 float x, yb;
1193 char *psf;
1194
1195 staff = s->staff;
1196 yb = staff_tb[staff].y;
1197 x = s->x;
1198
1199 /* if measure repeat, draw the '%' like glyphs */
1200 if (s->u.bar.len != 0) {
1201 struct SYMBOL *s2;
1202
1203 set_scale(s);
1204 if (s->u.bar.len == 1) {
1205 for (s2 = s->prev; s2->abc_type != ABC_T_REST; s2 = s2->prev)
1206 ;
1207 putxy(s2->x, yb + 12);
1208 a2b("mrep\n");
1209 } else {
1210 putxy(x, yb + 12);
1211 a2b("mrep2\n");
1212 if (s->voice == cursys->top_voice) {
1213 /*fixme set_font(s->gcf); */
1214 set_font(cfmt.anf);
1215 putxy(x, yb + staff_tb[staff].topbar + 4);
1216 a2b("M(%d)showc\n", s->u.bar.len);
1217 }
1218 }
1219 }
1220
1221 /* don't put a line between the staves if there is no bar above */
1222 if (staff != 0
1223 && s->ts_prev
1224 && (s->ts_prev->type != BAR || s->ts_prev->staff != staff - 1))
1225 h = staff_tb[staff].topbar * staff_tb[staff].staffscale;
1226
1227 bar_type = bar_cnv(s->u.bar.type);
1228 if (bar_type == 0)
1229 return; /* invisible */
1230 for (;;) {
1231 psf = "bar";
1232 switch (bar_type & 0x07) {
1233 case B_BAR:
1234 if (s->u.bar.dotted)
1235 psf = "dotbar";
1236 break;
1237 case B_OBRA:
1238 case B_CBRA:
1239 psf = "thbar";
1240 x -= 3;
1241 break;
1242 case B_COL:
1243 x -= 2;
1244 break;
1245 }
1246 switch (bar_type & 0x07) {
1247 default:
1248 set_sscale(-1);
1249 a2b("%.1f %.1f %.1f %s ", h, x, bot, psf);
1250 break;
1251 case B_COL:
1252 set_sscale(staff);
1253 putxy(x + 1, staff_tb[staff].y);
1254 a2b("rdots ");
1255 break;
1256 }
1257 bar_type >>= 4;
1258 if (bar_type == 0)
1259 break;
1260 x -= 3;
1261 }
1262 a2b("\n");
1263 }
1264
1265 /* -- draw a rest -- */
1266 /* (the staves are defined) */
draw_rest(struct SYMBOL * s)1267 static void draw_rest(struct SYMBOL *s)
1268 {
1269 int i, j, y, l;
1270 // int no_head;
1271 char *stafflines;
1272 float x, dotx, staffb;
1273 static char *rest_tb[NFLAGS_SZ] = {
1274 "r128", "r64", "r32", "r16", "r8",
1275 "r4",
1276 "r2", "r1", "r0", "r00"
1277 };
1278
1279 /* don't display the rests of invisible staves */
1280 /* (must do this here for voices out of their normal staff) */
1281 if (staff_tb[s->staff].empty)
1282 return;
1283
1284 /* if rest alone in the measure or measure repeat, center */
1285 if (s->dur == voice_tb[s->voice].meter.wmeasure
1286 || ((s->sflags & S_REPEAT) && s->doty >= 0)) {
1287 struct SYMBOL *s2;
1288
1289 /* don't use next/prev: there is no bar in voice averlay */
1290 s2 = s->ts_next;
1291 while (s2 && s2->time != s->time + s->dur)
1292 s2 = s2->ts_next;
1293 if (s2)
1294 x = s2->x;
1295 else
1296 x = realwidth;
1297 s2 = s;
1298 while (!(s2->sflags & S_SEQST))
1299 s2 = s2->ts_prev;
1300 s2 = s2->ts_prev;
1301 x = (x + s2->x) * .5;
1302
1303 /* center the associated decorations */
1304 if (s->u.note.dc.n > 0)
1305 deco_update(s, x - s->x);
1306 s->x = x;
1307 } else {
1308 x = s->x + s->u.note.notes[0].shhd * cur_scale;
1309 }
1310 if (s->flags & ABC_F_INVIS)
1311 // && !(s->sflags & S_OTHER_HEAD)) //fixme: before new deco struct
1312 return;
1313
1314 staffb = staff_tb[s->staff].y; /* bottom of staff */
1315
1316 if (s->sflags & S_REPEAT) {
1317 putxy(x, staffb + 12);
1318 if (s->doty < 0) {
1319 a2b("srep\n");
1320 } else {
1321 a2b("mrep\n");
1322 if (s->doty > 2
1323 && s->voice == cursys->top_voice) {
1324 /*fixme set_font(s->gcf); */
1325 set_font(cfmt.anf);
1326 putxy(x, staffb + 24 + 4);
1327 a2b("M(%d)showc\n", s->doty);
1328 }
1329 }
1330 return;
1331 }
1332
1333 y = s->y;
1334
1335 i = C_XFLAGS - s->nflags; /* rest_tb index */
1336 stafflines = staff_tb[s->staff].stafflines;
1337 l = strlen(stafflines);
1338 if (i == 7 && y == 12
1339 && l <= 2)
1340 y -= 6; /* semibreve a bit lower */
1341
1342 putxy(x, y + staffb); /* rest */
1343 a2b("%s ", s->u.note.notes[0].head ?
1344 s->u.note.notes[0].head : rest_tb[i]);
1345
1346 /* output ledger line(s) when greater than minim */
1347 if (i >= 6) {
1348 j = y / 6;
1349 switch (i) {
1350 default:
1351 if (j >= l - 1 || stafflines[j + 1] != '|') {
1352 putxy(x, y + staffb);
1353 a2b("hl1 ");
1354 }
1355 if (i == 9) { // longa
1356 y -= 6;
1357 j--;
1358 }
1359 break;
1360 case 7:
1361 y += 6;
1362 j++;
1363 case 6:
1364 break;
1365 }
1366 if (j >= l || stafflines[j] != '|') {
1367 putxy(x, y + staffb);
1368 a2b("hl1 ");
1369 }
1370 }
1371
1372 dotx = 8;
1373 for (i = 0; i < s->dots; i++) {
1374 a2b("%.1f 3 dt ", dotx);
1375 dotx += 3.5;
1376 }
1377 a2b("\n");
1378 }
1379
1380 /* -- draw grace notes -- */
1381 /* (the staves are defined) */
draw_gracenotes(struct SYMBOL * s)1382 static void draw_gracenotes(struct SYMBOL *s)
1383 {
1384 int yy;
1385 float x0, y0, x1, y1, x2, y2, x3, y3, bet1, bet2, dy1, dy2;
1386 struct SYMBOL *g, *last;
1387 struct BEAM bm;
1388
1389 /* draw the notes */
1390 bm.s2 = NULL; /* (draw flags) */
1391 for (g = s->extra; g; g = g->next) {
1392 if (g->type != NOTEREST)
1393 continue;
1394 if ((g->sflags & (S_BEAM_ST | S_BEAM_END)) == S_BEAM_ST) {
1395 if (annotate)
1396 anno_out(g, 'b');
1397 if (calculate_beam(&bm, g))
1398 draw_beams(&bm);
1399 }
1400 draw_note(g->x, g, bm.s2 == NULL);
1401 if (annotate)
1402 anno_out(s, 'g');
1403 if (g == bm.s2)
1404 bm.s2 = NULL; /* (draw flags again) */
1405
1406 if (g->flags & ABC_F_SAPPO) { /* (on 1st note only) */
1407 if (!g->next) { /* if one note */
1408 x1 = 9;
1409 y1 = g->stem > 0 ? 5 : -5;
1410 } else { /* many notes */
1411 x1 = (g->next->x - g->x) * .5 + 4;
1412 y1 = (g->ys + g->next->ys) * .5 - g->y;
1413 if (g->stem > 0)
1414 y1 -= 1;
1415 else
1416 y1 += 1;
1417 }
1418 putxy(x1, y1);
1419 a2b("g%ca\n", g->stem > 0 ? 'u' : 'd');
1420 }
1421 if (annotate
1422 && (g->sflags & (S_BEAM_ST | S_BEAM_END)) == S_BEAM_END)
1423 anno_out(g, 'e');
1424 if (!g->next)
1425 break; /* (keep the last note) */
1426 }
1427
1428 /* slur */
1429 if (voice_tb[s->voice].key.instr == K_HP /* no slur when bagpipe */
1430 || voice_tb[s->voice].key.instr == K_Hp
1431 || pipeformat
1432 || !cfmt.graceslurs
1433 || s->u.note.slur_st /* explicit slur */
1434 || !s->next
1435 || s->next->abc_type != ABC_T_NOTE)
1436 return;
1437 last = g;
1438 if (last->stem >= 0) {
1439 yy = 127;
1440 for (g = s->extra; g; g = g->next) {
1441 if (g->type != NOTEREST)
1442 continue;
1443 if (g->y < yy) {
1444 yy = g->y;
1445 last = g;
1446 }
1447 }
1448 x0 = last->x;
1449 y0 = last->y - 5;
1450 if (s->extra != last) {
1451 x0 -= 4;
1452 y0 += 1;
1453 }
1454 s = s->next;
1455 x3 = s->x - 1;
1456 if (s->stem < 0)
1457 x3 -= 4;
1458 y3 = 3 * (s->pits[0] - 18) - 5;
1459 dy1 = (x3 - x0) * .4;
1460 if (dy1 > 3)
1461 dy1 = 3;
1462 dy2 = dy1;
1463 bet1 = .2;
1464 bet2 = .8;
1465 if (y0 > y3 + 7) {
1466 x0 = last->x - 1;
1467 y0 += .5;
1468 y3 += 6.5;
1469 x3 = s->x - 5.5;
1470 dy1 = (y0 - y3) * .8;
1471 dy2 = (y0 - y3) * .2;
1472 bet1 = 0;
1473 } else if (y3 > y0 + 4) {
1474 y3 = y0 + 4;
1475 x0 = last->x + 2;
1476 y0 = last->y - 4;
1477 }
1478 } else {
1479 yy = -127;
1480 for (g = s->extra; g; g = g->next) {
1481 if (g->type != NOTEREST)
1482 continue;
1483 if (g->y > yy) {
1484 yy = g->y;
1485 last = g;
1486 }
1487 }
1488 x0 = last->x;
1489 y0 = last->y + 5;
1490 if (s->extra != last) {
1491 x0 -= 4;
1492 y0 -= 1;
1493 }
1494 s = s->next;
1495 x3 = s->x - 1;
1496 if (s->stem >= 0)
1497 x3 -= 2;
1498 y3 = 3 * (s->pits[s->nhd] - 18) + 5;
1499 dy1 = (x0 - x3) * .4;
1500 if (dy1 < -3)
1501 dy1 = -3;
1502 dy2 = dy1;
1503 bet1 = .2;
1504 bet2 = .8;
1505 if (y0 < y3 - 7) {
1506 x0 = last->x - 1;
1507 y0 -= .5;
1508 y3 -= 6.5;
1509 x3 = s->x - 5.5;
1510 dy1 = (y0 - y3) * .8;
1511 dy2 = (y0 - y3) * .2;
1512 bet1 = 0;
1513 } else if (y3 < y0 - 4) {
1514 y3 = y0 - 4;
1515 x0 = last->x + 2;
1516 y0 = last->y + 4;
1517 }
1518 }
1519
1520 x1 = bet1 * x3 + (1 - bet1) * x0;
1521 y1 = bet1 * y3 + (1 - bet1) * y0 - dy1;
1522 x2 = bet2 * x3 + (1 - bet2) * x0;
1523 y2 = bet2 * y3 + (1 - bet2) * y0 - dy2;
1524
1525 a2b("%.2f %.2f %.2f %.2f %.2f %.2f ",
1526 x1 - x0, y1 - y0,
1527 x2 - x0, y2 - y0,
1528 x3 - x0, y3 - y0);
1529 putxy(x0, y0 + staff_tb[s->staff].y);
1530 a2b("gsl\n");
1531 }
1532
1533 /* -- set the y offset of the dots -- */
setdoty(struct SYMBOL * s,signed char * y_tb)1534 static void setdoty(struct SYMBOL *s,
1535 signed char *y_tb)
1536 {
1537 int m, m1, y, doty;
1538
1539 /* set the normal offsets */
1540 doty = s->doty;
1541 for (m = 0; m <= s->nhd; m++) {
1542 y = 3 * (s->pits[m] - 18); /* note height on staff */
1543 if ((y % 6) == 0) {
1544 if (doty != 0)
1545 y -= 3;
1546 else
1547 y += 3;
1548 }
1549 y_tb[m] = y;
1550 }
1551
1552 /* dispatch and recenter the dots in the staff space */
1553 for (m = 0; m < s->nhd; m++) {
1554 if (y_tb[m + 1] > y_tb[m])
1555 continue;
1556 m1 = m;
1557 while (m1 > 0) {
1558 if (y_tb[m1] > y_tb[m1 - 1] + 6)
1559 break;
1560 m1--;
1561 }
1562 if (3 * (s->pits[m1] - 18) - y_tb[m1]
1563 < y_tb[m + 1] - 3 *
1564 (s->pits[m + 1] - 18)) {
1565 while (m1 <= m)
1566 y_tb[m1++] -= 6;
1567 } else {
1568 y_tb[m + 1] = y_tb[m] + 6;
1569 }
1570 }
1571 }
1572
1573 /* -- draw m-th head with accidentals and dots -- */
1574 /* (the staves are defined) */
draw_basic_note(float x,struct SYMBOL * s,int m,signed char * y_tb)1575 static void draw_basic_note(float x,
1576 struct SYMBOL *s,
1577 int m,
1578 signed char *y_tb)
1579 {
1580 struct note *note = &s->u.note.notes[m];
1581 int y, head, dots, nflags, acc;
1582 // int no_head;
1583 int old_color = -1;
1584 float staffb, shhd;
1585 char *p;
1586 char hd[32];
1587
1588 staffb = staff_tb[s->staff].y; /* bottom of staff */
1589 y = 3 * (s->pits[m] - 18); /* note height on staff */
1590 shhd = note->shhd * cur_scale;
1591
1592 if (s->flags & ABC_F_INVIS)
1593 return;
1594
1595 putxy(x + shhd, y + staffb); /* output x and y */
1596
1597 // /* special case when no head */
1598 // if (s->nohdi1 >= 0
1599 // && m >= s->nohdi1 && m < s->nohdi2) {
1600 // a2b("xydef"); /* set x y */
1601 // return;
1602 // }
1603
1604 identify_note(s, note->len, &head, &dots, &nflags);
1605 acc = note->acc;
1606
1607 /* output a ledger line if horizontal shift / chord
1608 * and note on a line */
1609 if (y % 6 == 0
1610 && shhd != (s->stem > 0 ? s->u.note.notes[0].shhd :
1611 s->u.note.notes[s->nhd].shhd)) {
1612 int yy;
1613
1614 yy = 0;
1615 if (y >= 30) {
1616 yy = y;
1617 if (yy % 6)
1618 yy -= 3;
1619 } else if (y <= -6) {
1620 yy = y;
1621 if (yy % 6)
1622 yy += 3;
1623 }
1624 if (yy) {
1625 putxy(x + shhd, yy + staffb);
1626 a2b("hl ");
1627 }
1628 }
1629
1630 /* draw the head */
1631 if (note->invisible) {
1632 p = "xydef";
1633 } else if ((p = note->head) != NULL) {
1634 snprintf(hd, sizeof hd, "%.*s", note->hlen, p);
1635 p = hd;
1636 a2b("2 copy xydef "); /* set x y */
1637 } else if (s->flags & ABC_F_GRACE) {
1638 p = "ghd";
1639 } else if (s->type == CUSTOS) {
1640 p = "custos";
1641 } else if ((s->sflags & S_PERC) && acc != 0) {
1642 sprintf(hd, "p%shd", acc_tb[acc & 0x07]);
1643 acc = 0;
1644 p = hd;
1645 } else {
1646 switch (head) {
1647 case H_OVAL:
1648 if (note->len < BREVE) {
1649 p = "HD";
1650 break;
1651 }
1652 if (s->head != H_SQUARE) {
1653 p = "HDD";
1654 break;
1655 }
1656 /* fall thru */
1657 case H_SQUARE:
1658 p = note->len < BREVE * 2 ? "breve" : "longa";
1659
1660 /* don't display dots on last note of the tune */
1661 if (!tsnext && s->next
1662 && s->next->type == BAR && !s->next->next)
1663 dots = 0;
1664 break;
1665 case H_EMPTY:
1666 p = "Hd"; break;
1667 default:
1668 p = "hd"; break;
1669 }
1670 }
1671 if (note->color >= 0) {
1672 old_color = cur_color;
1673 set_color(note->color);
1674 }
1675 a2b("%s", p);
1676
1677 /* draw the dots */
1678 /*fixme: to see for grace notes*/
1679 if (dots) {
1680 float dotx;
1681 int doty;
1682
1683 dotx = 7.7 + s->xmx - note->shhd;
1684 doty = y_tb[m] - y;
1685 if (scale_voice)
1686 doty /= cur_scale;
1687 while (--dots >= 0) {
1688 a2b(" %.1f %d dt", dotx, doty);
1689 dotx += 3.5;
1690 }
1691 }
1692
1693 /* draw the accidental */
1694 if (acc != 0) {
1695 x -= note->shac * cur_scale;
1696 a2b(" ");
1697 putx(x);
1698 a2b(s->flags & ABC_F_GRACE ? "gsc " : "y ");
1699 draw_acc(acc, s->u.note.microscale);
1700 if (s->flags & ABC_F_GRACE)
1701 a2b(" grestore");
1702 }
1703
1704 if (old_color >= 0) {
1705 a2b("\n");
1706 set_color(old_color);
1707 }
1708 }
1709
1710 /* -- draw a note or a chord -- */
1711 /* (the staves are defined) */
draw_note(float x,struct SYMBOL * s,int fl)1712 static void draw_note(float x,
1713 struct SYMBOL *s,
1714 int fl)
1715 {
1716 int m, ma;
1717 float staffb, slen, shhd;
1718 char c, *hltype;
1719 signed char y_tb[MAXHD];
1720
1721 if (s->dots)
1722 setdoty(s, y_tb);
1723 if (s->head >= H_OVAL)
1724 x += 1;
1725 staffb = staff_tb[s->staff].y;
1726
1727 /* output the ledger lines */
1728 if (!(s->flags & ABC_F_INVIS)) {
1729 if (s->flags & ABC_F_GRACE) {
1730 hltype = "ghl";
1731 } else {
1732 switch (s->head) {
1733 default:
1734 hltype = "hl";
1735 break;
1736 case H_OVAL:
1737 hltype = "hl1";
1738 break;
1739 case H_SQUARE:
1740 hltype = "hl2";
1741 break;
1742 }
1743 }
1744 shhd = (s->stem > 0 ? s->u.note.notes[0].shhd :
1745 s->u.note.notes[s->nhd].shhd)
1746 * cur_scale;
1747 if (s->pits[0] < 22)
1748 draw_hl(x + shhd, staffb, 0,
1749 3 * (s->pits[0] - 18), /* lower ledger lines */
1750 staff_tb[s->staff].stafflines, hltype);
1751 if (s->pits[s->nhd] > 22)
1752 draw_hl(x + shhd, staffb, 1,
1753 3 * (s->pits[s->nhd] - 18), /* upper ledger lines */
1754 staff_tb[s->staff].stafflines, hltype);
1755 }
1756
1757 /* draw the master note, first or last one */
1758 if (cfmt.setdefl)
1759 set_defl(s->stem >= 0 ? DEF_STEMUP : 0);
1760 ma = s->stem >= 0 ? 0 : s->nhd;
1761 draw_basic_note(x, s, ma, y_tb);
1762
1763 /* draw the stem and flags */
1764 if (!(s->flags & (ABC_F_INVIS | ABC_F_STEMLESS))) {
1765 char c2;
1766
1767 c = s->stem >= 0 ? 'u' : 'd';
1768 slen = (s->ys - s->y) / voice_tb[s->voice].scale;
1769 if (!fl || s->nflags - s->aux <= 0) { /* stem only */
1770 c2 = (s->flags & ABC_F_GRACE) ? 'g' : 's';
1771 if (s->nflags > 0) { /* (fix for PS low resolution) */
1772 if (s->stem >= 0)
1773 slen -= 1;
1774 else
1775 slen += 1;
1776 }
1777 a2b(" %.1f %c%c", slen, c2, c);
1778 } else { /* stem and flags */
1779 if (cfmt.straightflags)
1780 c = 's'; /* straight flag */
1781 c2 = (s->flags & ABC_F_GRACE) ? 'g' : 'f';
1782 a2b(" %d %.1f s%c%c", s->nflags - s->aux, slen, c2, c);
1783 }
1784 } else if (s->sflags & S_XSTEM) { /* cross-staff stem */
1785 struct SYMBOL *s2;
1786
1787 s2 = s->ts_prev;
1788 slen = (s2->stem > 0 ? s2->y : s2->ys) - s->y;
1789 slen += staff_tb[s2->staff].y - staffb;
1790 /*fixme:KO when different scales*/
1791 slen /= voice_tb[s->voice].scale;
1792 a2b(" %.1f su", slen);
1793 }
1794
1795 /* draw the tremolo bars */
1796 if (!(s->flags & ABC_F_INVIS)
1797 && fl
1798 && (s->sflags & S_TREM1)) {
1799 float x1;
1800
1801 x1 = x + (s->stem > 0 ? s->u.note.notes[0].shhd :
1802 s->u.note.notes[s->nhd].shhd)
1803 * cur_scale;
1804 slen = 3 * (s->pits[s->stem > 0 ? s->nhd : 0] - 18);
1805 if (s->head >= H_OVAL) {
1806 if (s->stem > 0)
1807 slen += 5 + 5.4 * s->aux;
1808 else
1809 slen -= 5 + 5.4;
1810 } else {
1811 x1 += ((s->flags & ABC_F_GRACE)
1812 ? GSTEM_XOFF : STEM_XOFF)
1813 * s->stem;
1814 if (s->stem > 0)
1815 slen += 6 + 5.4 * s->aux;
1816 else
1817 slen -= 6 + 5.4;
1818 }
1819 slen /= voice_tb[s->voice].scale;
1820 a2b(" %d ", s->aux);
1821 putxy(x1, staffb + slen);
1822 a2b("trem");
1823 }
1824
1825 /* draw the other note heads */
1826 for (m = 0; m <= s->nhd; m++) {
1827 if (m == ma)
1828 continue;
1829 a2b(" ");
1830 draw_basic_note(x, s, m, y_tb);
1831 }
1832 a2b("\n");
1833 }
1834
1835 /* -- find where to terminate/start a slur -- */
next_scut(struct SYMBOL * s)1836 static struct SYMBOL *next_scut(struct SYMBOL *s)
1837 {
1838 struct SYMBOL *prev;
1839
1840 prev = s;
1841 for (s = s->next; s; s = s->next) {
1842 if (s->type == BAR
1843 && ((s->sflags & S_RRBAR)
1844 || s->u.bar.type == B_THIN_THICK
1845 || s->u.bar.type == B_THICK_THIN
1846 || (s->u.bar.repeat_bar
1847 && s->text
1848 && s->text[0] != '1')))
1849 return s;
1850 prev = s;
1851 }
1852 /*fixme: KO when no note for this voice at end of staff */
1853 return prev;
1854 }
1855
prev_scut(struct SYMBOL * s)1856 struct SYMBOL *prev_scut(struct SYMBOL *s)
1857 {
1858 while (s->prev) {
1859 s = s->prev;
1860 if (s->type == BAR
1861 && ((s->sflags & S_RRBAR)
1862 || s->u.bar.type == B_THIN_THICK
1863 || s->u.bar.type == B_THICK_THIN
1864 || (s->u.bar.repeat_bar
1865 && s->text
1866 && s->text[0] != '1')))
1867 return s;
1868 }
1869
1870 /* return a symbol of any voice starting before the start of the voice */
1871 s = voice_tb[s->voice].sym;
1872 while (s->type != CLEF)
1873 s = s->ts_prev; /* search a main voice */
1874 if (s->next && s->next->type == KEYSIG)
1875 s = s->next;
1876 if (s->next && s->next->type == TIMESIG)
1877 s = s->next;
1878 return s;
1879 }
1880
1881 /* -- decide whether a slur goes up or down -- */
slur_direction(struct SYMBOL * k1,struct SYMBOL * k2)1882 static int slur_direction(struct SYMBOL *k1,
1883 struct SYMBOL *k2)
1884 {
1885 struct SYMBOL *s;
1886 int some_upstem, low;
1887
1888 if ((k1->flags & ABC_F_GRACE) && k1->stem > 0)
1889 return -1;
1890
1891 some_upstem = low = 0;
1892 for (s = k1; ; s = s->next) {
1893 if (s->abc_type == ABC_T_NOTE) {
1894 if (!(s->flags & ABC_F_STEMLESS)) {
1895 if (s->stem < 0)
1896 return 1;
1897 some_upstem = 1;
1898 }
1899 if (s->pits[0] < 22) /* if under middle staff */
1900 low = 1;
1901 }
1902 if (s == k2)
1903 break;
1904 }
1905 if (!some_upstem && !low)
1906 return 1;
1907 return -1;
1908 }
1909
1910 /* -- output a slur / tie -- */
slur_out(float x1,float y1,float x2,float y2,int s,float height,int dotted,int staff)1911 static void slur_out(float x1,
1912 float y1,
1913 float x2,
1914 float y2,
1915 int s,
1916 float height,
1917 int dotted,
1918 int staff) /* if < 0, the staves are defined */
1919 {
1920 float alfa, beta, mx, my, xx1, yy1, xx2, yy2, dx, dy, dz;
1921 float scale_y;
1922
1923 alfa = .3;
1924 beta = .45;
1925
1926 /* for wide flat slurs, make shape more square */
1927 dy = y2 - y1;
1928 if (dy < 0)
1929 dy = -dy;
1930 dx = x2 - x1;
1931 if (dx > 40. && dy / dx < .7) {
1932 alfa = .3 + .002 * (dx - 40.);
1933 if (alfa > .7)
1934 alfa = .7;
1935 }
1936
1937 /* alfa, beta, and height determine Bezier control points pp1,pp2
1938 *
1939 * X====alfa===|===alfa=====X
1940 * / | \
1941 * pp1 | pp2
1942 * / height \
1943 * beta | beta
1944 * / | \
1945 * p1 m p2
1946 *
1947 */
1948
1949 mx = .5 * (x1 + x2);
1950 my = .5 * (y1 + y2);
1951
1952 xx1 = mx + alfa * (x1 - mx);
1953 yy1 = my + alfa * (y1 - my) + height;
1954 xx1 = x1 + beta * (xx1 - x1);
1955 yy1 = y1 + beta * (yy1 - y1);
1956
1957 xx2 = mx + alfa * (x2 - mx);
1958 yy2 = my + alfa * (y2 - my) + height;
1959 xx2 = x2 + beta * (xx2 - x2);
1960 yy2 = y2 + beta * (yy2 - y2);
1961
1962 dx = .03 * (x2 - x1);
1963 // if (dx > 10.)
1964 // dx = 10.;
1965 // dy = 1.6 * s;
1966 dy = 2 * s;
1967 dz = .2 + .001 * (x2 - x1);
1968 if (dz > .6)
1969 dz = .6;
1970 dz *= s;
1971
1972 scale_y = scale_voice ? cur_scale : 1;
1973 if (!dotted)
1974 a2b("%.2f %.2f %.2f %.2f %.2f %.2f 0 %.2f ",
1975 (xx2 - dx - x2) / cur_scale,
1976 (yy2 + dy - y2 - dz) / scale_y,
1977 (xx1 + dx - x2) / cur_scale,
1978 (yy1 + dy - y2 - dz) / scale_y,
1979 (x1 - x2) / cur_scale,
1980 (y1 - y2 - dz) / scale_y,
1981 dz);
1982 a2b("%.2f %.2f %.2f %.2f %.2f %.2f ",
1983 (xx1 - x1) / cur_scale, (yy1 - y1) / scale_y,
1984 (xx2 - x1) / cur_scale, (yy2 - y1) / scale_y,
1985 (x2 - x1) / cur_scale, (y2 - y1) / scale_y);
1986 putxy(x1, y1);
1987 if (staff >= 0)
1988 a2b("y%d ", staff);
1989 a2b(dotted ? "dSL\n" : "SL\n");
1990 }
1991
1992 /* -- check if slur sequence in a multi-voice staff -- */
slur_multi(struct SYMBOL * k1,struct SYMBOL * k2)1993 static int slur_multi(struct SYMBOL *k1,
1994 struct SYMBOL *k2)
1995 {
1996 for (;;) {
1997 if (k1->multi != 0) /* if multi voice */
1998 /*fixme: may change*/
1999 return k1->multi;
2000 if (k1 == k2)
2001 break;
2002 k1 = k1->next;
2003 }
2004 return 0;
2005 }
2006
2007 /* -- draw a phrasing slur between two symbols -- */
2008 /* (the staves are not yet defined) */
2009 /* (not a pretty routine, this) */
draw_slur(struct SYMBOL * k1_orig,struct SYMBOL * k2,int m1,int m2,int slur_type)2010 static int draw_slur(struct SYMBOL *k1_orig,
2011 struct SYMBOL *k2,
2012 int m1,
2013 int m2,
2014 int slur_type)
2015 {
2016 struct SYMBOL *k1, *k;
2017 float x1, y1, x2, y2, height, addy;
2018 float a, y, z, h, dx, dy;
2019 int s, nn, upstaff, two_staves;
2020
2021 k1 = k1_orig;
2022 while (k1->voice != k2->voice)
2023 k1 = k1->ts_next;
2024
2025 /*fixme: if two staves, may have upper or lower slur*/
2026 switch (slur_type & 0x07) { /* (ignore dot bit) */
2027 case SL_ABOVE: s = 1; break;
2028 case SL_BELOW: s = -1; break;
2029 default:
2030 if ((s = slur_multi(k1, k2)) == 0)
2031 s = slur_direction(k1, k2);
2032 break;
2033 }
2034
2035 nn = 1;
2036 upstaff = k1->staff;
2037 two_staves = 0;
2038 if (k1 != k2)
2039 for (k = k1->next; k; k = k->next) {
2040 if (k->type == NOTEREST) {
2041 nn++;
2042 if (k->staff != upstaff) {
2043 two_staves = 1;
2044 if (k->staff < upstaff)
2045 upstaff = k->staff;
2046 }
2047 }
2048 if (k == k2)
2049 break;
2050 }
2051 /*fixme: KO when two staves*/
2052 if (two_staves) error(0, k1, "*** multi-staves slurs not treated yet");
2053
2054 /* fix endpoints */
2055 // x1 = k1->x + k1->xmx; /* take the max right side */
2056 x1 = k1_orig->x + k1_orig->u.note.notes[0].shhd;
2057 if (k1_orig != k2) {
2058 // x2 = k2->x;
2059 x2 = k2->x + k2->u.note.notes[0].shhd;
2060 } else { /* (the slur starts on last note of the line) */
2061 for (k = k2->ts_next; k; k = k->ts_next)
2062 if (k->sflags & S_NEW_SY)
2063 break;
2064 if (!k)
2065 x2 = realwidth;
2066 else
2067 x2 = k->x;
2068 }
2069
2070 if (m1 >= 0) {
2071 y1 = (float) (3 * (k1->pits[m1] - 18) + 5 * s);
2072 } else {
2073 y1 = (float) (s > 0 ? k1->ymx + 2 : k1->ymn - 2);
2074 if (k1->abc_type == ABC_T_NOTE) {
2075 if (s > 0) {
2076 if (k1->stem > 0) {
2077 x1 += 5;
2078 if ((k1->sflags & S_BEAM_END)
2079 && k1->nflags >= -1 /* if with a stem */
2080 //fixme: check if at end of tuplet
2081 && (!(k1->sflags & S_IN_TUPLET))) {
2082 // || k1->ys > y1 - 3)) {
2083 if (k1->nflags > 0) {
2084 x1 += 2;
2085 y1 = k1->ys - 3;
2086 } else {
2087 y1 = k1->ys - 6;
2088 }
2089 // don't clash with decorations
2090 // } else {
2091 // y1 = k1->ys + 3;
2092 }
2093 // } else {
2094 // y1 = k1->y + 8;
2095 }
2096 } else {
2097 if (k1->stem < 0) {
2098 x1 -= 1;
2099 if ((k1->sflags & S_BEAM_END)
2100 && k1->nflags >= -1
2101 && (!(k1->sflags & S_IN_TUPLET)
2102 || k1->ys < y1 + 3)) {
2103 if (k1->nflags > 0) {
2104 x1 += 2;
2105 y1 = k1->ys + 3;
2106 } else {
2107 y1 = k1->ys + 6;
2108 }
2109 // } else {
2110 // y1 = k1->ys - 3;
2111 }
2112 // } else {
2113 // y1 = k1->y - 8;
2114 }
2115 }
2116 }
2117 }
2118 if (m2 >= 0) {
2119 y2 = (float) (3 * (k2->pits[m2] - 18) + 5 * s);
2120 } else {
2121 y2 = (float) (s > 0 ? k2->ymx + 2 : k2->ymn - 2);
2122 if (k2->abc_type == ABC_T_NOTE) {
2123 if (s > 0) {
2124 if (k2->stem > 0) {
2125 x2 += 1;
2126 if ((k2->sflags & S_BEAM_ST)
2127 && k2->nflags >= -1
2128 && (!(k2->sflags & S_IN_TUPLET)))
2129 // || k2->ys > y2 - 3))
2130 y2 = k2->ys - 6;
2131 // else
2132 // y2 = k2->ys + 3;
2133 // } else {
2134 // y2 = k2->y + 8;
2135 }
2136 } else {
2137 if (k2->stem < 0) {
2138 x2 -= 5;
2139 if ((k2->sflags & S_BEAM_ST)
2140 && k2->nflags >= -1
2141 && (!(k2->sflags & S_IN_TUPLET)))
2142 // || k2->ys < y2 + 3))
2143 y2 = k2->ys + 6;
2144 // else
2145 // y2 = k2->ys - 3;
2146 // } else {
2147 // y2 = k2->y - 8;
2148 }
2149 }
2150 }
2151 }
2152
2153 if (k1->abc_type != ABC_T_NOTE) {
2154 y1 = y2 + 1.2 * s;
2155 x1 = k1->x + k1->wr * .5;
2156 if (x1 > x2 - 12)
2157 x1 = x2 - 12;
2158 }
2159
2160 if (k2->abc_type != ABC_T_NOTE) {
2161 if (k1->abc_type == ABC_T_NOTE)
2162 y2 = y1 + 1.2 * s;
2163 else
2164 y2 = y1;
2165 if (k1 != k2)
2166 x2 = k2->x - k2->wl * .3;
2167 }
2168
2169 if (nn >= 3) {
2170 if (k1->next->type != BAR
2171 && k1->next->x < x1 + 48) {
2172 if (s > 0) {
2173 y = k1->next->ymx - 2;
2174 if (y1 < y)
2175 y1 = y;
2176 } else {
2177 y = k1->next->ymn + 2;
2178 if (y1 > y)
2179 y1 = y;
2180 }
2181 }
2182 if (k2->prev
2183 && k2->prev->type != BAR
2184 && k2->prev->x > x2 - 48) {
2185 if (s > 0) {
2186 y = k2->prev->ymx - 2;
2187 if (y2 < y)
2188 y2 = y;
2189 } else {
2190 y = k2->prev->ymn + 2;
2191 if (y2 > y)
2192 y2 = y;
2193 }
2194 }
2195 }
2196
2197 a = (y2 - y1) / (x2 - x1); /* slur steepness */
2198 if (a > SLUR_SLOPE || a < -SLUR_SLOPE) {
2199 if (a > SLUR_SLOPE)
2200 a = SLUR_SLOPE;
2201 else
2202 a = -SLUR_SLOPE;
2203 if (a * s > 0)
2204 y1 = y2 - a * (x2 - x1);
2205 else
2206 y2 = y1 + a * (x2 - x1);
2207 }
2208
2209 /* for big vertical jump, shift endpoints */
2210 y = y2 - y1;
2211 if (y > 8)
2212 y = 8;
2213 else if (y < -8)
2214 y = -8;
2215 z = y;
2216 if (z < 0)
2217 z = -z;
2218 dx = .5 * z;
2219 dy = .3 * y;
2220 if (y * s > 0) {
2221 x2 -= dx;
2222 y2 -= dy;
2223 } else {
2224 x1 += dx;
2225 y1 += dy;
2226 }
2227
2228 /* special case for grace notes */
2229 if (k1->flags & ABC_F_GRACE)
2230 x1 = k1->x - GSTEM_XOFF * .5;
2231 if (k2->flags & ABC_F_GRACE)
2232 x2 = k2->x + GSTEM_XOFF * 1.5;
2233
2234 h = 0;
2235 a = (y2 - y1) / (x2 - x1);
2236 if (k1 != k2
2237 && k1->voice == k2->voice) {
2238 addy = y1 - a * x1;
2239 for (k = k1->next; k != k2 ; k = k->next) {
2240 if (k->staff != upstaff)
2241 continue;
2242 switch (k->type) {
2243 case NOTEREST:
2244 if (s > 0) {
2245 y = 3 * (k->pits[k->nhd] - 18) + 6;
2246 if (y < k->ymx)
2247 y = k->ymx;
2248 y -= a * k->x + addy;
2249 if (y > h)
2250 h = y;
2251 } else {
2252 y = 3 * (k->pits[0] - 18) - 6;
2253 if (y > k->ymn)
2254 y = k->ymn;
2255 y -= a * k->x + addy;
2256 if (y < h)
2257 h = y;
2258 }
2259 break;
2260 case GRACE: {
2261 struct SYMBOL *g;
2262
2263 for (g = k->extra; g; g = g->next) {
2264 #if 1
2265 if (g->type != NOTEREST)
2266 continue;
2267 if (s > 0) {
2268 y = 3 * (g->pits[g->nhd] - 18) + 6;
2269 if (y < g->ymx)
2270 y = g->ymx;
2271 y -= a * g->x + addy;
2272 if (y > h)
2273 h = y;
2274 } else {
2275 y = 3 * (g->pits[0] - 18) - 6;
2276 if (y > g->ymn)
2277 y = g->ymn;
2278 y -= a * g->x + addy;
2279 if (y < h)
2280 h = y;
2281 }
2282 #else
2283 y = g->y - a * k->x - addy;
2284 if (s > 0) {
2285 y += GSTEM + 2;
2286 if (y > h)
2287 h = y;
2288 } else {
2289 y -= 2;
2290 if (y < h)
2291 h = y;
2292 }
2293 #endif
2294 }
2295 break;
2296 }
2297 }
2298 }
2299 y1 += .45 * h;
2300 y2 += .45 * h;
2301 h *= .65;
2302 }
2303
2304 if (nn > 3)
2305 height = (.08 * (x2 - x1) + 12) * s;
2306 else
2307 height = (.03 * (x2 - x1) + 8) * s;
2308 if (s > 0) {
2309 if (height < 3 * h)
2310 height = 3 * h;
2311 if (height > 40)
2312 height = 40;
2313 } else {
2314 if (height > 3 * h)
2315 height = 3 * h;
2316 if (height < -40)
2317 height = -40;
2318 }
2319
2320 y = y2 - y1;
2321 if (y < 0)
2322 y = -y;
2323 if (s > 0) {
2324 if (height < .8 * y)
2325 height = .8 * y;
2326 } else {
2327 if (height > -.8 * y)
2328 height = -.8 * y;
2329 }
2330 height *= cfmt.slurheight;
2331
2332 slur_out(x1, y1, x2, y2, s, height, slur_type & SL_DOTTED, upstaff);
2333
2334 /* have room for other symbols */
2335 dx = x2 - x1;
2336 a = (y2 - y1) / dx;
2337 /*fixme: it seems to work with .4, but why?*/
2338 addy = y1 - a * x1 + .4 * height;
2339 if (k1->voice == k2->voice)
2340 for (k = k1; k != k2; k = k->next) {
2341 if (k->staff != upstaff)
2342 continue;
2343 y = a * k->x + addy;
2344 if (k->ymx < y)
2345 k->ymx = y;
2346 else if (k->ymn > y)
2347 k->ymn = y;
2348 if (k->next == k2) {
2349 dx = x2;
2350 if (k2->sflags & S_SL1)
2351 dx -= 5;
2352 } else {
2353 dx = k->next->x;
2354 }
2355 if (k != k1)
2356 x1 = k->x;
2357 dx -= x1;
2358 y_set(upstaff, s > 0, x1, dx, y);
2359 }
2360 return (s > 0 ? SL_ABOVE : SL_BELOW) | (slur_type & SL_DOTTED);
2361 }
2362
2363 /* -- draw the slurs between 2 symbols --*/
draw_slurs(struct SYMBOL * first,struct SYMBOL * last)2364 static void draw_slurs(struct SYMBOL *first,
2365 struct SYMBOL *last)
2366 {
2367 struct SYMBOL *s, *s1, *k, *gr1, *gr2;
2368 int i, m1, m2, gr1_out, slur_type, cont;
2369
2370 gr1 = gr2 = NULL;
2371 s = first;
2372 for (;;) {
2373 if (!s || s == last) {
2374 if (!gr1
2375 || !(s = gr1->next)
2376 || s == last)
2377 break;
2378 gr1 = NULL;
2379 }
2380 if (s->type == GRACE) {
2381 gr1 = s;
2382 s = s->extra;
2383 continue;
2384 }
2385 if ((s->type != NOTEREST && s->type != SPACE)
2386 || (s->u.note.slur_st == 0
2387 && !(s->sflags & S_SL1))) {
2388 s = s->next;
2389 continue;
2390 }
2391 k = NULL; /* find matching slur end */
2392 s1 = s->next;
2393 gr1_out = 0;
2394 for (;;) {
2395 if (!s1) {
2396 if (gr2) {
2397 s1 = gr2->next;
2398 gr2 = NULL;
2399 continue;
2400 }
2401 if (!gr1 || gr1_out)
2402 break;
2403 s1 = gr1->next;
2404 gr1_out = 1;
2405 continue;
2406 }
2407 if (s1->type == GRACE) {
2408 gr2 = s1;
2409 s1 = s1->extra;
2410 continue;
2411 }
2412 if (s1->type == BAR
2413 && ((s1->sflags & S_RRBAR)
2414 || s1->u.bar.type == B_THIN_THICK
2415 || s1->u.bar.type == B_THICK_THIN
2416 || (s1->u.bar.repeat_bar
2417 && s1->text
2418 && s1->text[0] != '1'))) {
2419 k = s1;
2420 break;
2421 }
2422 if (s1->type != NOTEREST && s1->type != SPACE) {
2423 s1 = s1->next;
2424 continue;
2425 }
2426 if (s1->u.note.slur_end
2427 || (s1->sflags & S_SL2)) {
2428 k = s1;
2429 break;
2430 }
2431 if (s1->u.note.slur_st
2432 || (s1->sflags & S_SL1)) {
2433 if (gr2) { /* if in grace note sequence */
2434 for (k = s1; k->next; k = k->next)
2435 ;
2436 k->next = gr2->next;
2437 if (gr2->next)
2438 gr2->next->prev = k;
2439 // gr2->u.note.slur_st = SL_AUTO;
2440 k = NULL;
2441 }
2442 draw_slurs(s1, last);
2443 if (gr2
2444 && gr2->next) {
2445 gr2->next->prev->next = NULL;
2446 gr2->next->prev = gr2;
2447 }
2448 }
2449 if (s1 == last)
2450 break;
2451 s1 = s1->next;
2452 }
2453 if (!s1) {
2454 k = next_scut(s);
2455 } else if (!k) {
2456 s = s1;
2457 if (s == last)
2458 break;
2459 continue;
2460 }
2461
2462 /* if slur in grace note sequence, change the linkages */
2463 if (gr1) {
2464 for (s1 = s; s1->next; s1 = s1->next)
2465 ;
2466 s1->next = gr1->next;
2467 if (gr1->next)
2468 gr1->next->prev = s1;
2469 gr1->u.note.slur_st = SL_AUTO;
2470 }
2471 if (gr2) {
2472 gr2->prev->next = gr2->extra;
2473 gr2->extra->prev = gr2->prev;
2474 gr2->u.note.slur_st = SL_AUTO;
2475 }
2476 if (s->u.note.slur_st) {
2477 slur_type = s->u.note.slur_st & 0x0f;
2478 s->u.note.slur_st >>= 4;
2479 m1 = -1;
2480 } else {
2481 for (m1 = 0; m1 <= s->nhd; m1++)
2482 if (s->u.note.notes[m1].sl1)
2483 break;
2484 slur_type = s->u.note.notes[m1].sl1 & 0x0f;
2485 s->u.note.notes[m1].sl1 >>= 4;
2486 if (s->u.note.notes[m1].sl1 == 0) {
2487 for (i = m1 + 1; i <= s->nhd; i++)
2488 if (s->u.note.notes[i].sl1)
2489 break;
2490 if (i > s->nhd)
2491 s->sflags &= ~S_SL1;
2492 }
2493 }
2494 m2 = -1;
2495 cont = 0;
2496 if ((k->type == NOTEREST || k->type == SPACE)
2497 && (k->u.note.slur_end
2498 || (k->sflags & S_SL2))) {
2499 if (k->u.note.slur_end) {
2500 k->u.note.slur_end--;
2501 } else {
2502 for (m2 = 0; m2 <= k->nhd; m2++)
2503 if (k->u.note.notes[m2].sl2)
2504 break;
2505 k->u.note.notes[m2].sl2--;
2506 if (k->u.note.notes[m2].sl2 == 0) {
2507 for (i = m2 + 1; i <= k->nhd; i++)
2508 if (k->u.note.notes[i].sl2)
2509 break;
2510 if (i > k->nhd)
2511 k->sflags &= ~S_SL2;
2512 }
2513 }
2514 } else {
2515 if (k->type != BAR
2516 || (!(k->sflags & S_RRBAR)
2517 && k->u.bar.type != B_THIN_THICK
2518 && k->u.bar.type != B_THICK_THIN
2519 && (!k->u.bar.repeat_bar
2520 || !k->text
2521 || k->text[0] == '1')))
2522 cont = 1;
2523 }
2524 slur_type = draw_slur(s, k, m1, m2, slur_type);
2525 if (cont) {
2526 /*fixme: the slur types are inverted*/
2527 voice_tb[k->voice].slur_st <<= 4;
2528 voice_tb[k->voice].slur_st += slur_type;
2529 }
2530
2531 /* if slur in grace note sequence, restore the linkages */
2532 if (gr1
2533 && gr1->next) {
2534 gr1->next->prev->next = NULL;
2535 gr1->next->prev = gr1;
2536 }
2537 if (gr2) {
2538 gr2->prev->next = gr2;
2539 gr2->extra->prev = NULL;
2540 }
2541
2542 if (s->u.note.slur_st
2543 || (s->sflags & S_SL1))
2544 continue;
2545 if (s == last)
2546 break;
2547 s = s->next;
2548 }
2549 }
2550
2551 /* -- draw a tuplet -- */
2552 /* (the staves are not yet defined) */
2553 /* See http://moinejf.free.fr/abcm2ps-doc/tuplets.xhtml
2554 * about the value of 'aux' */
draw_tuplet(struct SYMBOL * t,struct SYMBOL * s)2555 static struct SYMBOL *draw_tuplet(struct SYMBOL *t, /* tuplet in extra */
2556 struct SYMBOL *s) /* main note */
2557 {
2558 struct SYMBOL *s1, *s2, *sy, *next, *g;
2559 int r, upstaff, nb_only, some_slur, dir;
2560 float x1, x2, y1, y2, xm, ym, a, s0, yy, yx, dy;
2561
2562 next = s;
2563 if ((t->aux & 0xf000) == 0x1000) /* if 'when' == never */
2564 goto done;
2565
2566 /* treat the nested tuplets starting on this symbol */
2567 for (g = t->next; g; g = g->next) {
2568 if (g->type == TUPLET) {
2569 sy = draw_tuplet(g, s);
2570 if (sy->time > next->time)
2571 next = sy;
2572 }
2573 }
2574
2575 /* search the first and last notes/rests of the tuplet */
2576 r = t->u.tuplet.r_plet;
2577 s1 = NULL;
2578 some_slur = 0;
2579 upstaff = s->staff;
2580 for (s2 = s; s2; s2 = s2->next) {
2581 if (s2 != s
2582 && (s2->sflags & S_IN_TUPLET)) {
2583 for (g = s2->extra; g; g = g->next) {
2584 if (g->type == TUPLET) {
2585 sy = draw_tuplet(g, s2);
2586 if (sy->time > next->time)
2587 next = sy;
2588 }
2589 }
2590 }
2591 if (s2->type != NOTEREST) {
2592 if (s2->type == GRACE) {
2593 for (g = s2->extra; g; g = g->next) {
2594 if (g->type != NOTEREST)
2595 continue;
2596 if (g->u.note.slur_st
2597 || (g->sflags & S_SL1))
2598 some_slur = 1;
2599 }
2600 }
2601 continue;
2602 }
2603 if (s2->u.note.slur_st /* if slur start/end */
2604 || s2->u.note.slur_end
2605 || (s2->sflags & (S_SL1 | S_SL2)))
2606 some_slur = 1;
2607 if (s2->staff < upstaff)
2608 upstaff = s2->staff;
2609 if (!s1)
2610 s1 = s2;
2611 if (--r <= 0)
2612 break;
2613 }
2614 if (!s2)
2615 goto done; /* no solution... */
2616 if (s2->time > next->time)
2617 next = s2;
2618
2619 dir = t->aux & 0x000f;
2620 if (!dir)
2621 dir = s1->stem > 0 ? SL_ABOVE : SL_BELOW;
2622
2623 if (s1 == s2) { /* tuplet with 1 note (!) */
2624 nb_only = 1;
2625 } else if ((t->aux & 0x0f00) == 0x0100) { /* 'what' == slur */
2626 nb_only = 1;
2627 draw_slur(s1, s2, -1, -1, dir);
2628 } else {
2629
2630 /* search if a bracket is needed */
2631 if ((t->aux & 0xf000) == 0x2000 /* if 'when' == always */
2632 || s1->abc_type != ABC_T_NOTE || s2->abc_type != ABC_T_NOTE) {
2633 nb_only = 0;
2634 } else {
2635 nb_only = 1;
2636 for (sy = s1; ; sy = sy->next) {
2637 if (sy->type != NOTEREST) {
2638 if (sy->type == GRACE
2639 || sy->type == SPACE)
2640 continue;
2641 nb_only = 0;
2642 break;
2643 }
2644 if (sy == s2)
2645 break;
2646 if (sy->sflags & S_BEAM_END) {
2647 nb_only = 0;
2648 break;
2649 }
2650 }
2651 if (nb_only
2652 && !(s1->sflags & (S_BEAM_ST | S_BEAM_BR1 | S_BEAM_BR2))) {
2653 for (sy = s1->prev; sy; sy = sy->prev) {
2654 if (sy->type == NOTEREST) {
2655 if (sy->nflags >= s1->nflags)
2656 nb_only = 0;
2657 break;
2658 }
2659 }
2660 }
2661 if (nb_only && !(s2->sflags & S_BEAM_END)) {
2662 for (sy = s2->next; sy; sy = sy->next) {
2663 if (sy->type == NOTEREST) {
2664 if (!(sy->sflags & (S_BEAM_BR1 | S_BEAM_BR2))
2665 && sy->nflags >= s2->nflags)
2666 nb_only = 0;
2667 break;
2668 }
2669 }
2670 }
2671 }
2672 }
2673
2674 /* if number only, draw it */
2675 if (nb_only) {
2676 float a, b;
2677
2678 if ((t->aux & 0x00f0) == 0x0010) /* if 'which' == none */
2679 goto done;
2680 xm = (s2->x + s1->x) * .5;
2681 if (s1 == s2) /* tuplet with 1 note */
2682 a = 0;
2683 else
2684 a = (s2->ys - s1->ys) / (s2->x - s1->x);
2685 b = s1->ys - a * s1->x;
2686 yy = a * xm + b;
2687 if (dir == SL_ABOVE) {
2688 ym = y_get(s1->staff, 1, xm - 3, 6);
2689 if (ym > yy)
2690 b += ym - yy;
2691 b += 2;
2692 } else {
2693 ym = y_get(s1->staff, 0, xm - 3, 6);
2694 if (ym < yy)
2695 b += ym - yy;
2696 b -= 10;
2697 }
2698 for (sy = s1; ; sy = sy->next) {
2699 if (sy->x >= xm)
2700 break;
2701 }
2702 if (s1->stem * s2->stem > 0) {
2703 if (s1->stem > 0)
2704 xm += GSTEM_XOFF;
2705 else
2706 xm -= GSTEM_XOFF;
2707 }
2708 ym = a * xm + b;
2709 if ((t->aux & 0x00f0) == 0) /* if 'which' == number */
2710 a2b("(%d)", t->u.tuplet.p_plet);
2711 else
2712 a2b("(%d:%d)", t->u.tuplet.p_plet, t->u.tuplet.q_plet);
2713 putxy(xm, ym);
2714 a2b("y%d bnum\n", s1->staff);
2715
2716 if (dir == SL_ABOVE) {
2717 ym += 8;
2718 if (sy->ymx < ym)
2719 sy->ymx = (short) ym;
2720 y_set(s1->staff, 1, xm - 3, 6, ym);
2721 } else {
2722 if (sy->ymn > ym)
2723 sy->ymn = (short) ym;
2724 y_set(s1->staff, 0, xm - 3, 6, ym);
2725 }
2726 goto done;
2727 }
2728
2729 /* draw the slurs when inside the tuplet */
2730 if (some_slur) {
2731 draw_slurs(s1, s2);
2732 if (s1->u.note.slur_st
2733 || (s1->sflags & S_SL1))
2734 return next;
2735 for (sy = s1->next; sy != s2; sy = sy->next) {
2736 if (sy->u.note.slur_st /* if slur start/end */
2737 || sy->u.note.slur_end
2738 || (sy->sflags & (S_SL1 | S_SL2)))
2739 return next; /* don't draw now */
2740 }
2741
2742 /* don't draw the tuplet when a slur ends on the last note */
2743 if (s2->u.note.slur_end
2744 || (s2->sflags & S_SL2))
2745 return next;
2746 }
2747
2748 if ((t->aux & 0x0f00) != 0) /* if 'what' != square */
2749 fprintf(stderr, "'what' value of %%%%tuplets not yet coded\n");
2750
2751 /*fixme: two staves not treated*/
2752 /*fixme: to optimize*/
2753 dir = t->aux & 0x000f; /* 'where' */
2754 if (!dir)
2755 dir = s1->multi >= 0 ? SL_ABOVE : SL_BELOW;
2756 if (dir == SL_ABOVE) {
2757
2758 /* sole or upper voice: the bracket is above the staff */
2759 x1 = s1->x - 4;
2760 y1 = 24;
2761 if (s1->staff == upstaff) {
2762 sy = s1;
2763 if (sy->abc_type != ABC_T_NOTE) {
2764 for (sy = sy->next; sy != s2; sy = sy->next)
2765 if (sy->abc_type == ABC_T_NOTE)
2766 break;
2767 }
2768 ym = y_get(upstaff, 1, sy->x, 0);
2769 if (ym > y1)
2770 y1 = ym;
2771 if (s1->stem > 0)
2772 x1 += 3;
2773 }
2774 y2 = 24;
2775 if (s2->staff == upstaff) {
2776 sy = s2;
2777 if (sy->abc_type != ABC_T_NOTE) {
2778 for (sy = sy->prev; sy != s1; sy = sy->prev)
2779 if (sy->abc_type == ABC_T_NOTE)
2780 break;
2781 }
2782 ym = y_get(upstaff, 1, sy->x, 0);
2783 if (ym > y2)
2784 y2 = ym;
2785 }
2786
2787 /* end the backet according to the last note duration */
2788 if (s2->dur > s2->prev->dur) {
2789 if (s2->next)
2790 x2 = s2->next->x - s2->next->wl - 5;
2791 else
2792 x2 = realwidth - 6;
2793 } else {
2794 x2 = s2->x + 4;
2795 r = s2->stem >= 0 ? 0 : s2->nhd;
2796 if (s2->u.note.notes[r].shhd > 0)
2797 x2 += s2->u.note.notes[r].shhd;
2798 if (s2->staff == upstaff
2799 && s2->stem > 0)
2800 x2 += 3.5;
2801 }
2802
2803 xm = .5 * (x1 + x2);
2804 ym = .5 * (y1 + y2);
2805
2806 a = (y2 - y1) / (x2 - x1);
2807 s0 = 3 * (s2->pits[s2->nhd] -
2808 s1->pits[s1->nhd]) / (x2 - x1);
2809 if (s0 > 0) {
2810 if (a < 0)
2811 a = 0;
2812 else if (a > s0)
2813 a = s0;
2814 } else {
2815 if (a > 0)
2816 a = 0;
2817 else if (a < s0)
2818 a = s0;
2819 }
2820 if (a * a < .1 * .1)
2821 a = 0;
2822
2823 /* shift up bracket if needed */
2824 dy = 0;
2825 for (sy = s1; ; sy = sy->next) {
2826 if (sy->dur == 0 /* not a note or a rest */
2827 || sy->staff != upstaff) {
2828 if (sy == s2)
2829 break;
2830 continue;
2831 }
2832 yy = ym + (sy->x - xm) * a;
2833 yx = y_get(upstaff, 1, sy->x, 0);
2834 if (yx - yy > dy)
2835 dy = yx - yy;
2836 if (sy == s2)
2837 break;
2838 }
2839
2840 ym += dy + 2;
2841 y1 = ym + a * (x1 - xm);
2842 y2 = ym + a * (x2 - xm);
2843 putxy(x2 - x1, y2 - y1);
2844 putxy(x1, y1 + 4);
2845 a2b("y%d tubr", upstaff);
2846
2847 /* shift the slurs / decorations */
2848 ym += 8;
2849 for (sy = s1; ; sy = sy->next) {
2850 if (sy->staff == upstaff) {
2851 yy = ym + (sy->x - xm) * a;
2852 if (sy->ymx < yy)
2853 sy->ymx = yy;
2854 if (sy == s2)
2855 break;
2856 y_set(upstaff, 1, sy->x, sy->next->x - sy->x, yy);
2857 } else if (sy == s2) {
2858 break;
2859 }
2860 }
2861
2862 } else { /* lower voice of the staff: the bracket is below the staff */
2863 /*fixme: think to all that again..*/
2864 x1 = s1->x - 7;
2865
2866 if (s2->dur > s2->prev->dur) {
2867 if (s2->next)
2868 x2 = s2->next->x - s2->next->wl - 8;
2869 else
2870 x2 = realwidth - 6;
2871 } else {
2872 x2 = s2->x + 2;
2873 if (s2->u.note.notes[s2->nhd].shhd > 0)
2874 x2 += s2->u.note.notes[s2->nhd].shhd;
2875 }
2876
2877 if (s1->staff == upstaff) {
2878 sy = s1;
2879 if (sy->abc_type != ABC_T_NOTE) {
2880 for (sy = sy->next; sy != s2; sy = sy->next)
2881 if (sy->abc_type == ABC_T_NOTE)
2882 break;
2883 }
2884 y1 = y_get(upstaff, 0, sy->x, 0);
2885 } else {
2886 y1 = 0;
2887 }
2888 if (s2->staff == upstaff) {
2889 sy = s2;
2890 if (sy->abc_type != ABC_T_NOTE) {
2891 for (sy = sy->prev; sy != s1; sy = sy->prev)
2892 if (sy->abc_type == ABC_T_NOTE)
2893 break;
2894 }
2895 y2 = y_get(upstaff, 0, sy->x, 0);
2896 } else {
2897 y2 = 0;
2898 }
2899
2900 xm = .5 * (x1 + x2);
2901 ym = .5 * (y1 + y2);
2902
2903 a = (y2 - y1) / (x2 - x1);
2904 s0 = 3 * (s2->pits[0] - s1->pits[0]) / (x2 - x1);
2905 if (s0 > 0) {
2906 if (a < 0)
2907 a = 0;
2908 else if (a > s0)
2909 a = s0;
2910 } else {
2911 if (a > 0)
2912 a = 0;
2913 else if (a < s0)
2914 a = s0;
2915 }
2916 if (a * a < .1 * .1)
2917 a = 0;
2918
2919 /* shift down bracket if needed */
2920 dy = 0;
2921 for (sy = s1; ; sy = sy->next) {
2922 if (sy->dur == 0 /* not a note nor a rest */
2923 || sy->staff != upstaff) {
2924 if (sy == s2)
2925 break;
2926 continue;
2927 }
2928 yy = ym + (sy->x - xm) * a;
2929 yx = y_get(upstaff, 0, sy->x, 0);
2930 if (yx - yy < dy)
2931 dy = yx - yy;
2932 if (sy == s2)
2933 break;
2934 }
2935
2936 ym += dy - 10;
2937 y1 = ym + a * (x1 - xm);
2938 y2 = ym + a * (x2 - xm);
2939 putxy(x2 - x1, y2 - y1);
2940 putxy(x1, y1 + 4);
2941 a2b("y%d tubrl",upstaff);
2942
2943 /* shift the slurs / decorations */
2944 ym -= 2;
2945 for (sy = s1; ; sy = sy->next) {
2946 if (sy->staff == upstaff) {
2947 if (sy == s2)
2948 break;
2949 yy = ym + (sy->x - xm) * a;
2950 if (sy->ymn > yy)
2951 sy->ymn = (short) yy;
2952 y_set(upstaff, 0, sy->x, sy->next->x - sy->x, yy);
2953 }
2954 if (sy == s2)
2955 break;
2956 }
2957 } /* lower voice */
2958
2959 if ((t->aux & 0x00f0) == 0x10) { /* if 'which' == none */
2960 a2b("\n");
2961 goto done;
2962 }
2963 yy = .5 * (y1 + y2);
2964 if ((t->aux & 0x00f0) == 0) /* if 'which' == number */
2965 a2b("(%d)", t->u.tuplet.p_plet);
2966 else
2967 a2b("(%d:%d)", t->u.tuplet.p_plet, t->u.tuplet.q_plet);
2968 putxy(xm, yy);
2969 a2b("y%d bnumb\n", upstaff);
2970
2971 done:
2972 s->sflags &= ~S_IN_TUPLET;
2973 return next;
2974 }
2975
2976 /* -- draw the ties between two notes/chords -- */
draw_note_ties(struct SYMBOL * k1,struct SYMBOL * k2,int ntie,unsigned char * mhead1,unsigned char * mhead2,int job)2977 static void draw_note_ties(struct SYMBOL *k1,
2978 struct SYMBOL *k2,
2979 int ntie,
2980 unsigned char *mhead1,
2981 unsigned char *mhead2,
2982 int job)
2983 {
2984 int i, s, m1, m2, p, p1, p2, y, staff;
2985 float x1, x2, h, sh;
2986
2987 for (i = 0; i < ntie; i++) {
2988 m1 = mhead1[i];
2989 p1 = k1->pits[m1];
2990 m2 = mhead2[i];
2991 p2 = job != 2 ? k2->pits[m2] : p1;
2992 s = (k1->u.note.notes[m1].ti1 & 0x07) == SL_ABOVE ? 1 : -1;
2993
2994 x1 = k1->x;
2995 sh = k1->u.note.notes[m1].shhd; /* head shift */
2996 if (s > 0) {
2997 if (m1 < k1->nhd && p1 + 1 == k1->pits[m1 + 1])
2998 if (k1->u.note.notes[m1 + 1].shhd > sh)
2999 sh = k1->u.note.notes[m1 + 1].shhd;
3000 } else {
3001 if (m1 > 0 && p1 == k1->pits[m1 - 1] + 1)
3002 if (k1->u.note.notes[m1 - 1].shhd > sh)
3003 sh = k1->u.note.notes[m1 - 1].shhd;
3004 }
3005 // x1 += sh;
3006 x1 += sh * 0.6;
3007
3008 x2 = k2->x;
3009 if (job != 2) {
3010 sh = k2->u.note.notes[m2].shhd;
3011 if (s > 0) {
3012 if (m2 < k2->nhd && p2 + 1 == k2->pits[m2 + 1])
3013 if (k2->u.note.notes[m2 + 1].shhd < sh)
3014 sh = k2->u.note.notes[m2 + 1].shhd;
3015 } else {
3016 if (m2 > 0 && p2 == k2->pits[m2 - 1] + 1)
3017 if (k2->u.note.notes[m2 - 1].shhd < sh)
3018 sh = k2->u.note.notes[m2 - 1].shhd;
3019 }
3020 x2 += sh * 0.6;
3021 }
3022
3023 staff = k1->staff;
3024 switch (job) {
3025 case 0:
3026 if (p1 == p2 || (p1 & 1))
3027 p = p1;
3028 else
3029 p = p2;
3030 break;
3031 case 3: /* clef or staff change */
3032 s = -s;
3033 // fall thru
3034 case 1: /* no starting note */
3035 x1 = k1->x;
3036 if (x1 > x2 - 20)
3037 x1 = x2 - 20;
3038 p = p2;
3039 staff = k2->staff;
3040 break;
3041 /* case 2: * no ending note */
3042 default:
3043 if (k1 != k2) {
3044 if (k2->type == BAR)
3045 x2 -= 2;
3046 else
3047 x2 -= k2->wl;
3048 } else {
3049 struct SYMBOL *k;
3050 int time;
3051
3052 time = k1->time + k1->dur;
3053 for (k = k1->ts_next; k; k = k->ts_next)
3054 if (k->time > time)
3055 break;
3056 if (!k)
3057 x2 = realwidth;
3058 else
3059 x2 = k->x;
3060 }
3061 if (x2 < x1 + 16)
3062 x2 = x1 + 16;
3063 p = p1;
3064 break;
3065 }
3066 if (x2 - x1 > 20) {
3067 x1 += 3.5;
3068 x2 -= 3.5;
3069 } else {
3070 x1 += 1.5;
3071 x2 -= 1.5;
3072 }
3073
3074 y = 3 * (p - 18);
3075 //fixme: clash when 2 ties on second interval chord
3076 // if (p & 1)
3077 // y += 2 * s;
3078 #if 0
3079 if (job != 1 && job != 3) {
3080 if (s > 0) {
3081 // if (k1->nflags > -2 && k1->stem > 0
3082 // && k1->nhd == 0)
3083 // x1 += 4.5;
3084 if (!(p & 1) && k1->dots > 0)
3085 y = 3 * (p - 18) + 6;
3086 }
3087 // } else {
3088 // if (s < 0) {
3089 // if (k2->nflags > -2 && k2->stem < 0
3090 // && k2->nhd == 0)
3091 // x2 -= 4.5;
3092 // }
3093 }
3094 #endif
3095
3096 h = (.04 * (x2 - x1) + 10) * s;
3097 slur_out(x1, staff_tb[staff].y + y,
3098 x2, staff_tb[staff].y + y,
3099 s, h, k1->u.note.notes[m1].ti1 & SL_DOTTED, -1);
3100 }
3101 }
3102
3103 /* -- draw ties between neighboring notes/chords -- */
draw_ties(struct SYMBOL * k1,struct SYMBOL * k2,int job)3104 static void draw_ties(struct SYMBOL *k1,
3105 struct SYMBOL *k2,
3106 int job) /* 0: normal
3107 * 1: no starting note
3108 * 2: no ending note
3109 * 3: no start for clef or staff change */
3110 {
3111 struct SYMBOL *k3;
3112 int i, m1, nh1, pit, ntie, tie2, ntie3, time;
3113 unsigned char mhead1[MAXHD], mhead2[MAXHD], mhead3[MAXHD];
3114
3115 time = k1->time + k1->dur;
3116 ntie = ntie3 = 0;
3117 nh1 = k1->nhd;
3118
3119 /* half ties from last note in line or before new repeat */
3120 if (job == 2) {
3121 for (i = 0; i <= nh1; i++) {
3122 if (k1->u.note.notes[i].ti1)
3123 mhead3[ntie3++] = i;
3124 }
3125 draw_note_ties(k1, k2 ? k2 : k1, ntie3, mhead3, mhead3, job);
3126 return;
3127 }
3128
3129 /* set up list of ties to draw */
3130 for (i = 0; i <= nh1; i++) {
3131 if (k1->u.note.notes[i].ti1 == 0)
3132 continue;
3133 tie2 = -1;
3134 pit = k1->u.note.notes[i].pit;
3135 for (m1 = k2->nhd; m1 >= 0; m1--) {
3136 switch (k2->u.note.notes[m1].pit - pit) {
3137 case 1: /* maybe ^c - _d */
3138 case -1: /* _d - ^c */
3139 if (k1->u.note.notes[i].acc != k2->u.note.notes[m1].acc)
3140 tie2 = m1;
3141 default:
3142 continue;
3143 case 0:
3144 tie2 = m1;
3145 break;
3146 }
3147 break;
3148 }
3149 if (tie2 >= 0) { /* 1st or 2nd choice */
3150 mhead1[ntie] = i;
3151 mhead2[ntie++] = tie2;
3152 } else {
3153 mhead3[ntie3++] = i; /* no match */
3154 }
3155 }
3156
3157 /* draw the ties */
3158 draw_note_ties(k1, k2, ntie, mhead1, mhead2, job);
3159
3160 /* if any bad tie, try an other voice of the same staff */
3161 if (ntie3 == 0)
3162 return; /* no bad tie */
3163 k3 = k1->ts_next;
3164 while (k3 && k3->time < time)
3165 k3 = k3->ts_next;
3166 while (k3 && k3->time == time) {
3167 if (k3->abc_type != ABC_T_NOTE
3168 || k3->staff != k1->staff) {
3169 k3 = k3->ts_next;
3170 continue;
3171 }
3172 ntie = 0;
3173 for (i = ntie3; --i >= 0; ) {
3174 pit = k1->u.note.notes[mhead3[i]].pit;
3175 for (m1 = k3->nhd; m1 >= 0; m1--) {
3176 if (k3->u.note.notes[m1].pit == pit) {
3177 mhead1[ntie] = mhead3[i];
3178 mhead2[ntie++] = m1;
3179 ntie3--;
3180 // mhead3[i] = mhead3[--ntie3];
3181 break;
3182 }
3183 }
3184 }
3185 if (ntie > 0) {
3186 draw_note_ties(k1, k3,
3187 ntie, mhead1, mhead2,
3188 job == 1 ? 1 : 0);
3189 if (ntie3 == 0)
3190 return;
3191 }
3192 k3 = k3->ts_next;
3193 }
3194
3195 // if (ntie3 != 0)
3196 error(1, k1, "Bad tie");
3197 }
3198
draw_ties_g(struct SYMBOL * s1,struct SYMBOL * s2,int job)3199 static void draw_ties_g(struct SYMBOL *s1,
3200 struct SYMBOL *s2,
3201 int job)
3202 {
3203 struct SYMBOL *g;
3204
3205 if (s1->type == GRACE) {
3206 for (g = s1->extra; g; g = g->next) {
3207 if (g->sflags & S_TI1)
3208 draw_ties(g, s2, job);
3209 }
3210 } else {
3211 draw_ties(s1, s2, job);
3212 }
3213 }
3214
3215 /* -- try to get the symbol of a ending tie when combined voices -- */
tie_comb(struct SYMBOL * s)3216 static struct SYMBOL *tie_comb(struct SYMBOL *s)
3217 {
3218 struct SYMBOL *s1;
3219 int time, st;
3220
3221 time = s->time + s->dur;
3222 st = s->staff;
3223 for (s1 = s->ts_next; s1; s1 = s1->ts_next) {
3224 if (s1->staff != st)
3225 continue;
3226 if (s1->time == time) {
3227 if (s1->abc_type == ABC_T_NOTE)
3228 return s1;
3229 continue;
3230 }
3231 if (s1->time > time)
3232 return s; // bad tie
3233 }
3234 return NULL; // no ending tie
3235 }
3236
3237 /* -- draw all ties between neighboring notes -- */
draw_all_ties(struct VOICE_S * p_voice)3238 static void draw_all_ties(struct VOICE_S *p_voice)
3239 {
3240 struct SYMBOL *s1, *s2, *s3, *s4, *rtie;
3241 struct SYMBOL tie;
3242 int clef_chg, time;
3243
3244 for (s1 = p_voice->sym; s1; s1 = s1->next) {
3245 switch (s1->type) {
3246 case CLEF:
3247 case KEYSIG:
3248 case TIMESIG:
3249 continue;
3250 }
3251 break;
3252 }
3253 rtie = p_voice->rtie; /* tie from 1st repeat bar */
3254 for (s2 = s1; s2; s2 = s2->next) {
3255 // if (s2->abc_type == ABC_T_NOTE
3256 if (s2->dur
3257 || s2->type == GRACE)
3258 break;
3259 if (s2->type != BAR
3260 || !s2->u.bar.repeat_bar
3261 || !s2->text)
3262 continue;
3263 if (s2->text[0] == '1') /* 1st repeat bar */
3264 rtie = p_voice->tie;
3265 else
3266 p_voice->tie = rtie;
3267 }
3268 if (!s2)
3269 return;
3270 if (p_voice->tie) { /* tie from previous line */
3271 p_voice->tie->x = s1->x + s1->wr;
3272 s1 = p_voice->tie;
3273 p_voice->tie = NULL;
3274 s1->staff = s2->staff;
3275 s1->ts_next = s2->ts_next; /* (for tie to other voice) */
3276 s1->time = s2->time - s1->dur; /* (if after repeat sequence) */
3277 draw_ties(s1, s2, 1); /* tie to 1st note */
3278 }
3279
3280 /* search the start of ties */
3281 clef_chg = 0;
3282 for (;;) {
3283 for (s1 = s2; s1; s1 = s1->next) {
3284 if (s1->sflags & S_TI1)
3285 break;
3286 if (!rtie)
3287 continue;
3288 if (s1->type != BAR
3289 || !s1->u.bar.repeat_bar
3290 || !s1->text)
3291 continue;
3292 if (s1->text[0] == '1') { /* 1st repeat bar */
3293 rtie = NULL;
3294 continue;
3295 }
3296 if (s1->u.bar.type == B_BAR)
3297 continue; // not a repeat
3298 for (s2 = s1->next; s2; s2 = s2->next)
3299 if (s2->abc_type == ABC_T_NOTE)
3300 break;
3301 if (!s2) {
3302 s1 = NULL;
3303 break;
3304 }
3305 memcpy(&tie, rtie, sizeof tie);
3306 // tie.x = s1->x + s1->wr;
3307 tie.x = s1->x;
3308 tie.next = s2;
3309 tie.staff = s2->staff;
3310 tie.time = s2->time - tie.dur;
3311 draw_ties(&tie, s2, 1);
3312 }
3313 if (!s1)
3314 break;
3315
3316 /* search the end of the tie
3317 * and notice the clef changes (may occur in an other voice) */
3318 time = s1->time + s1->dur;
3319 for (s2 = s1->next; s2; s2 = s2->next) {
3320 if (s2->dur != 0)
3321 break;
3322 if (s2->type == BAR
3323 && s2->u.bar.repeat_bar
3324 && s2->text) {
3325 if (s2->text[0] != '1')
3326 break;
3327 rtie = s1; /* 1st repeat bar */
3328 }
3329 }
3330 if (!s2) {
3331 for (s4 = s1->ts_next; s4; s4 = s4->ts_next) {
3332 if (s4->staff != s1->staff)
3333 continue;
3334 if (s4->time < time)
3335 continue;
3336 if (s4->time > time) {
3337 s4 = NULL;
3338 break;
3339 }
3340 if (s4->dur != 0)
3341 break;
3342 }
3343 if (!s4) {
3344 draw_ties_g(s1, NULL, 2);
3345 p_voice->tie = s1;
3346 break;
3347 }
3348 } else {
3349 if (s2->abc_type != ABC_T_NOTE
3350 && s2->abc_type != ABC_T_BAR) {
3351 error(1, s1, "Bad tie");
3352 continue;
3353 }
3354 if (s2->time == time) {
3355 s4 = s2;
3356 } else {
3357 s4 = tie_comb(s1);
3358 if (s4 == s1) {
3359 error(1, s1, "Bad tie");
3360 continue;
3361 }
3362 }
3363 }
3364 for (s3 = s1->ts_next; s3; s3 = s3->ts_next) {
3365 if (s3->staff != s1->staff)
3366 continue;
3367 if (s3->time > time)
3368 break;
3369 if (s3->type == CLEF) {
3370 clef_chg = 1;
3371 continue;
3372 }
3373 #if 0
3374 if (s3->type == BAR) {
3375 // if ((s3->sflags & S_RRBAR)
3376 // || s3->u.bar.type == B_THIN_THICK
3377 // || s3->u.bar.type == B_THICK_THIN) {
3378 // s4 = s3;
3379 // break;
3380 // }
3381 if (!s3->u.bar.repeat_bar
3382 || !s3->text)
3383 continue;
3384 if (s3->text[0] != '1') {
3385 s4 = s3;
3386 break;
3387 }
3388 rtie = s1; /* 1st repeat bar */
3389 }
3390 #endif
3391 }
3392
3393 /* ties with clef or staff change */
3394 if (clef_chg || s1->staff != s4->staff) {
3395 float x, dx;
3396
3397 clef_chg = 0;
3398 dx = (s4->x - s1->x) * 0.4;
3399 x = s4->x;
3400 s4->x -= dx;
3401 if (s4->x > s1->x + 32.)
3402 s4->x = s1->x + 32.;
3403 draw_ties_g(s1, s4, 2);
3404 s4->x = x;
3405 x = s1->x;
3406 s1->x += dx;
3407 if (s1->x < s4->x - 24.)
3408 s1->x = s4->x - 24.;
3409 draw_ties(s1, s4, 3);
3410 s1->x = x;
3411 continue;
3412 }
3413 draw_ties_g(s1, s4, s4->abc_type == ABC_T_NOTE ? 0 : 2);
3414 }
3415 p_voice->rtie = rtie;
3416 }
3417
3418 /* -- draw all phrasing slurs for one staff -- */
3419 /* (the staves are not yet defined) */
draw_all_slurs(struct VOICE_S * p_voice)3420 static void draw_all_slurs(struct VOICE_S *p_voice)
3421 {
3422 struct SYMBOL *s, *k;
3423 int i, m2, slur_type;
3424 unsigned char slur_st;
3425
3426 s = p_voice->sym;
3427 if (!s)
3428 return;
3429 slur_type = p_voice->slur_st;
3430 p_voice->slur_st = 0;
3431
3432 /* the starting slur types are inverted */
3433 slur_st = 0;
3434 while (slur_type != 0) {
3435 slur_st <<= 4;
3436 slur_st |= (slur_type & 0x0f);
3437 slur_type >>= 4;
3438 }
3439
3440 /* draw the slurs inside the music line */
3441 draw_slurs(s, NULL);
3442
3443 /* do unbalanced slurs still left over */
3444 for ( ; s; s = s->next) {
3445 if (s->type != NOTEREST && s->type != SPACE)
3446 continue;
3447 while (s->u.note.slur_end
3448 || (s->sflags & S_SL2)) {
3449 if (s->u.note.slur_end) {
3450 s->u.note.slur_end--;
3451 m2 = -1;
3452 } else {
3453 for (m2 = 0; m2 <= s->nhd; m2++)
3454 if (s->u.note.notes[m2].sl2)
3455 break;
3456 s->u.note.notes[m2].sl2--;
3457 if (s->u.note.notes[m2].sl2 == 0) {
3458 for (i = m2 + 1; i <= s->nhd; i++)
3459 if (s->u.note.notes[i].sl2)
3460 break;
3461 if (i > s->nhd)
3462 s->sflags &= ~S_SL2;
3463 }
3464 }
3465 slur_type = slur_st & 0x0f;
3466 k = prev_scut(s);
3467 draw_slur(k, s, -1, m2, slur_type);
3468 if (k->type != BAR
3469 || (!(k->sflags & S_RRBAR)
3470 && k->u.bar.type != B_THIN_THICK
3471 && k->u.bar.type != B_THICK_THIN
3472 && (!k->u.bar.repeat_bar
3473 || !k->text
3474 || k->text[0] == '1')))
3475 slur_st >>= 4;
3476 }
3477 }
3478 s = p_voice->sym;
3479 while (slur_st != 0) {
3480 slur_type = slur_st & 0x0f;
3481 slur_st >>= 4;
3482 k = next_scut(s);
3483 draw_slur(s, k, -1, -1, slur_type);
3484 if (k->type != BAR
3485 || (!(k->sflags & S_RRBAR)
3486 && k->u.bar.type != B_THIN_THICK
3487 && k->u.bar.type != B_THICK_THIN
3488 && (!k->u.bar.repeat_bar
3489 || !k->text
3490 || k->text[0] == '1'))) {
3491 /*fixme: the slur types are inverted again*/
3492 p_voice->slur_st <<= 4;
3493 p_voice->slur_st += slur_type;
3494 }
3495 }
3496 }
3497
3498 /* -- work out accidentals to be applied to each note -- */
setmap(int sf,unsigned char * map)3499 static void setmap(int sf, /* number of sharps/flats in key sig (-7 to +7) */
3500 unsigned char *map) /* for 7 notes only */
3501 {
3502 int j;
3503
3504 for (j = 7; --j >= 0; )
3505 map[j] = A_NULL;
3506 switch (sf) {
3507 case 7: map[6] = A_SH;
3508 case 6: map[2] = A_SH;
3509 case 5: map[5] = A_SH;
3510 case 4: map[1] = A_SH;
3511 case 3: map[4] = A_SH;
3512 case 2: map[0] = A_SH;
3513 case 1: map[3] = A_SH;
3514 break;
3515 case -7: map[3] = A_FT;
3516 case -6: map[0] = A_FT;
3517 case -5: map[4] = A_FT;
3518 case -4: map[1] = A_FT;
3519 case -3: map[5] = A_FT;
3520 case -2: map[2] = A_FT;
3521 case -1: map[6] = A_FT;
3522 break;
3523 }
3524 }
3525
3526 /* output a tablature string escaping the parenthesis */
tbl_out(char * s,float x,int j,char * f)3527 static void tbl_out(char *s, float x, int j, char *f)
3528 {
3529 char *p;
3530
3531 a2b("(");
3532 p = s;
3533 for (;;) {
3534 while (*p != '\0' && *p != '(' && *p != ')' )
3535 p++;
3536 if (p != s) {
3537 a2b("%.*s", (int) (p - s), s);
3538 s = p;
3539 }
3540 if (*p == '\0')
3541 break;
3542 a2b("\\");
3543 p++;
3544 }
3545 a2b(")%.1f y %d %s ", x, j, f);
3546 }
3547
3548 /* -- draw the tablature with w: -- */
draw_tblt_w(struct VOICE_S * p_voice,int nly,float y,struct tblt_s * tblt)3549 static void draw_tblt_w(struct VOICE_S *p_voice,
3550 int nly,
3551 float y,
3552 struct tblt_s *tblt)
3553 {
3554 struct SYMBOL *s;
3555 struct lyrics *ly;
3556 struct lyl *lyl;
3557 char *p;
3558 int j, l;
3559
3560 a2b("/y{%.1f yns%d}def ", y, p_voice->staff);
3561 set_font(VOCALFONT);
3562 a2b("%.1f 0 y %d %s\n", realwidth, nly, tblt->head);
3563 for (j = 0; j < nly ; j++) {
3564 for (s = p_voice->sym; s; s = s->next) {
3565 ly = s->ly;
3566 if (!ly
3567 || (lyl = ly->lyl[j]) == NULL) {
3568 if (s->type == BAR) {
3569 if (!tblt->bar)
3570 continue;
3571 p = &tex_buf[16];
3572 *p-- = '\0';
3573 l = bar_cnv(s->u.bar.type);
3574 while (l != 0) {
3575 *p-- = "?|[]:???"[l & 0x07];
3576 l >>= 4;
3577 }
3578 p++;
3579 tbl_out(p, s->x, j, tblt->bar);
3580 }
3581 continue;
3582 }
3583 tbl_out(lyl->t, s->x, j, tblt->note);
3584 }
3585 a2b("\n");
3586 }
3587 }
3588
3589 /* -- draw the tablature with automatic pitch -- */
draw_tblt_p(struct VOICE_S * p_voice,float y,struct tblt_s * tblt)3590 static void draw_tblt_p(struct VOICE_S *p_voice,
3591 float y,
3592 struct tblt_s *tblt)
3593 {
3594 struct SYMBOL *s;
3595 int j, pitch, octave, sf, tied, acc;
3596 unsigned char workmap[70]; /* sharps/flats - base: lowest 'C' */
3597 unsigned char basemap[7];
3598 static int scale[7] = {0, 2, 4, 5, 7, 9, 11}; /* index = natural note */
3599 static int acc_pitch[6] = {0, 1, 0, -1, 2, -2}; /* index = enum accidentals */
3600
3601 sf = p_voice->key.sf;
3602 setmap(sf, basemap);
3603 for (j = 0; j < 10; j++)
3604 memcpy(&workmap[7 * j], basemap, 7);
3605 a2b("gsave 0 %.1f yns%d T(%.2s)%s\n", y, p_voice->staff,
3606 tblt->instr, tblt->head);
3607 tied = 0;
3608 for (s = p_voice->sym; s; s = s->next) {
3609 switch (s->type) {
3610 case NOTEREST:
3611 if (s->abc_type == ABC_T_REST)
3612 continue;
3613 if (tied) {
3614 tied = s->u.note.notes[0].ti1;
3615 continue;
3616 }
3617 break;
3618 case KEYSIG:
3619 sf = s->u.key.sf;
3620 setmap(sf, basemap);
3621 for (j = 0; j < 10; j++)
3622 memcpy(&workmap[7 * j], basemap, 7);
3623 continue;
3624 case BAR:
3625 if (s->flags & ABC_F_INVIS)
3626 continue;
3627 for (j = 0; j < 10; j++)
3628 memcpy(&workmap[7 * j], basemap, 7);
3629 continue;
3630 default:
3631 continue;
3632 }
3633 pitch = s->u.note.notes[0].pit + 19;
3634 acc = s->u.note.notes[0].acc;
3635 if (acc != 0) {
3636 workmap[pitch] = acc == A_NT
3637 ? A_NULL
3638 : (acc & 0x07);
3639 }
3640 pitch = scale[pitch % 7]
3641 + acc_pitch[workmap[pitch]]
3642 + 12 * (pitch / 7)
3643 - tblt->pitch;
3644 octave = 0;
3645 while (pitch < 0) {
3646 pitch += 12;
3647 octave--;
3648 }
3649 while (pitch >= 36) {
3650 pitch -= 12;
3651 octave++;
3652 }
3653 if ((acc & 0xf8) == 0) {
3654 a2b("%d %d %.2f %s\n", octave, pitch, s->x, tblt->note);
3655 } else {
3656 int n, d;
3657 float micro_p;
3658
3659 n = parse.micro_tb[acc >> 3];
3660 d = (n & 0xff) + 1;
3661 n = (n >> 8) + 1;
3662 switch (acc & 0x07) {
3663 case A_FT:
3664 case A_DF:
3665 n = -n;
3666 break;
3667 }
3668 micro_p = (float) pitch + (float) n / d;
3669 a2b("%d %.3f %.2f %s\n", octave, micro_p, s->x, tblt->note);
3670 }
3671 tied = s->u.note.notes[0].ti1;
3672 }
3673 a2b("grestore\n");
3674 }
3675
3676 /* -- draw the lyrics under (or above) notes -- */
3677 /* !! this routine is tied to set_width() !! */
draw_lyric_line(struct VOICE_S * p_voice,int j)3678 static void draw_lyric_line(struct VOICE_S *p_voice,
3679 int j)
3680 {
3681 struct SYMBOL *s;
3682 struct lyrics *ly;
3683 struct lyl *lyl;
3684 int hyflag, l, lflag;
3685 int ft, curft, defft;
3686 char *p;
3687 float lastx, w;
3688 float x0, shift;
3689
3690 hyflag = lflag = 0;
3691 if (p_voice->hy_st & (1 << j)) {
3692 hyflag = 1;
3693 p_voice->hy_st &= ~(1 << j);
3694 }
3695 for (s = p_voice->sym; /*s*/; s = s->next)
3696 if (s->type != CLEF
3697 && s->type != KEYSIG && s->type != TIMESIG)
3698 break;
3699 if (s->prev)
3700 lastx = s->prev->x;
3701 else
3702 lastx = tsfirst->x;
3703 x0 = 0;
3704 for ( ; s; s = s->next) {
3705 ly = s->ly;
3706 if (!ly
3707 || (lyl = ly->lyl[j]) == NULL) {
3708 switch (s->type) {
3709 case NOTEREST:
3710 if (s->abc_type == ABC_T_NOTE)
3711 break;
3712 /* fall thru */
3713 case MREST:
3714 if (lflag) {
3715 putx(x0 - lastx);
3716 putx(lastx + 3);
3717 a2b("y wln ");
3718 lflag = 0;
3719 lastx = s->x + s->wr;
3720 }
3721 }
3722 continue;
3723 }
3724 #if 1
3725 ft = lyl->f - cfmt.font_tb;
3726 get_str_font(&curft, &defft);
3727 if (ft != curft) {
3728 set_str_font(ft, defft);
3729 }
3730 #else
3731 if (lyl->f != f) { /* font change */
3732 f = lyl->f;
3733 str_font(f - cfmt.font_tb);
3734 if (lskip < f->size * 1.1)
3735 lskip = f->size * 1.1;
3736 }
3737 #endif
3738 p = lyl->t;
3739 w = lyl->w;
3740 shift = lyl->s;
3741 if (hyflag) {
3742 if (*p == LY_UNDER) { /* '_' */
3743 *p = LY_HYPH;
3744 } else if (*p != LY_HYPH) { /* not '-' */
3745 putx(s->x - shift - lastx);
3746 putx(lastx);
3747 a2b("y hyph ");
3748 hyflag = 0;
3749 lastx = s->x + s->wr;
3750 }
3751 }
3752 if (lflag
3753 && *p != LY_UNDER) { /* not '_' */
3754 putx(x0 - lastx + 3);
3755 putx(lastx + 3);
3756 a2b("y wln ");
3757 lflag = 0;
3758 lastx = s->x + s->wr;
3759 }
3760 if (*p == LY_HYPH /* '-' */
3761 || *p == LY_UNDER) { /* '_' */
3762 if (x0 == 0 && lastx > s->x - 18)
3763 lastx = s->x - 18;
3764 if (*p == LY_HYPH)
3765 hyflag = 1;
3766 else
3767 lflag = 1;
3768 x0 = s->x - shift;
3769 continue;
3770 }
3771 x0 = s->x - shift;
3772 l = strlen(p) - 1;
3773 if (p[l] == LY_HYPH) { /* '-' at end */
3774 p[l] = '\0';
3775 hyflag = 1;
3776 }
3777 putx(x0);
3778 a2b("y M ");
3779 put_str(p, A_LYRIC);
3780 lastx = x0 + w;
3781 }
3782 if (hyflag) {
3783 x0 = realwidth - 10;
3784 if (x0 < lastx + 10)
3785 x0 = lastx + 10;
3786 putx(x0 - lastx);
3787 putx(lastx);
3788 a2b("y hyph ");
3789 if (cfmt.hyphencont)
3790 p_voice->hy_st |= (1 << j);
3791 }
3792
3793 /* see if any underscore in the next line */
3794 for (s = tsnext; s; s = s->ts_next)
3795 if (s->voice == p_voice - voice_tb)
3796 break;
3797 for ( ; s; s = s->next) {
3798 if (s->abc_type == ABC_T_NOTE) {
3799 if (s->ly && s->ly->lyl[j]
3800 && s->ly->lyl[j]->t[0] == LY_UNDER) {
3801 lflag = 1;
3802 x0 = realwidth - 15;
3803 if (x0 < lastx + 12)
3804 x0 = lastx + 12;
3805 }
3806 break;
3807 }
3808 }
3809 if (lflag) {
3810 putx(x0 - lastx + 3);
3811 putx(lastx + 3);
3812 a2b("y wln");
3813 }
3814 a2b("\n");
3815 }
3816
draw_lyrics(struct VOICE_S * p_voice,int nly,float * h,float y,int incr)3817 static float draw_lyrics(struct VOICE_S *p_voice,
3818 int nly,
3819 float *h,
3820 float y,
3821 int incr) /* 1: below, -1: above */
3822 {
3823 int j, top;
3824 float sc;
3825
3826 /* check if the lyrics contain tablatures */
3827 if (p_voice->tblts[0]) {
3828 if (p_voice->tblts[0]->pitch == 0)
3829 return y; /* yes */
3830 if (p_voice->tblts[1]
3831 && p_voice->tblts[1]->pitch == 0)
3832 return y; /* yes */
3833 }
3834
3835 str_font(VOCALFONT);
3836 outft = -1; /* force font output */
3837 sc = staff_tb[p_voice->staff].staffscale;
3838
3839 /* under the staff */
3840 if (incr > 0) {
3841 if (y > -cfmt.vocalspace)
3842 y = -cfmt.vocalspace;
3843 y += h[0] / 6; // descent
3844 y *= sc;
3845 for (j = 0; j < nly; j++) {
3846 y -= h[j] * 1.1;
3847 a2b("/y{%.1f yns%d}! ", y, p_voice->staff);
3848 draw_lyric_line(p_voice, j);
3849 }
3850 return (y - h[j - 1] / 6) / sc;
3851 }
3852
3853 /* above the staff */
3854 top = staff_tb[p_voice->staff].topbar + cfmt.vocalspace;
3855 if (y < top)
3856 y = top;
3857 y += h[nly - 1] / 6; // descent
3858 y *= sc;
3859 for (j = nly; --j >= 0; ) {
3860 a2b("/y{%.1f yns%d}! ", y, p_voice->staff);
3861 draw_lyric_line(p_voice, j);
3862 y += h[j] * 1.1;
3863 }
3864 return y / sc;
3865 }
3866
3867 /* -- draw all the lyrics and the tablatures -- */
3868 /* (the staves are not yet defined) */
draw_all_lyrics(void)3869 static void draw_all_lyrics(void)
3870 {
3871 struct VOICE_S *p_voice;
3872 struct SYMBOL *s;
3873 int staff, voice, nly, i;
3874 struct {
3875 short a, b;
3876 float top, bot;
3877 } lyst_tb[MAXSTAFF];
3878 struct {
3879 int nly;
3880 float h[MAXLY];
3881 } lyvo_tb[MAXVOICE];
3882 char above_tb[MAXVOICE];
3883 char rv_tb[MAXVOICE];
3884 float top, bot, y, sc;
3885
3886 /* check if any lyric */
3887 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
3888 if (p_voice->have_ly
3889 || p_voice->tblts[0])
3890 break;
3891 }
3892 if (!p_voice)
3893 return;
3894
3895 /* compute the number of lyrics per voice - staff
3896 * and their y offset on the staff */
3897 memset(above_tb, 0, sizeof above_tb);
3898 memset(lyvo_tb, 0, sizeof lyvo_tb);
3899 memset(lyst_tb, 0, sizeof lyst_tb);
3900 staff = -1;
3901 top = bot = 0;
3902 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
3903 if (!p_voice->sym)
3904 continue;
3905 voice = p_voice - voice_tb;
3906 if (p_voice->staff != staff) {
3907 top = 0;
3908 bot = 0;
3909 staff = p_voice->staff;
3910 }
3911 nly = -1;
3912 if (p_voice->have_ly) {
3913 for (s = p_voice->sym; s; s = s->next) {
3914 struct lyrics *ly;
3915 float x, w;
3916
3917 ly = s->ly;
3918 if (!ly)
3919 continue;
3920 /*fixme:should get the real width*/
3921 x = s->x;
3922 if (ly->lyl[0]) {
3923 x -= ly->lyl[0]->s;
3924 w = ly->lyl[0]->w;
3925 } else {
3926 w = 10;
3927 }
3928 y = y_get(p_voice->staff, 1, x, w);
3929 if (top < y)
3930 top = y;
3931 y = y_get(p_voice->staff, 0, x, w);
3932 if (bot > y)
3933 bot = y;
3934 for (i = 0; i < MAXLY; i++) {
3935 if (!ly->lyl[i])
3936 continue;
3937 if (i > nly)
3938 nly = i;
3939 if (lyvo_tb[voice].h[i] < ly->lyl[i]->f->size)
3940 lyvo_tb[voice].h[i] =
3941 ly->lyl[i]->f->size;
3942 }
3943 }
3944 } else {
3945 y = y_get(p_voice->staff, 1, 0, realwidth);
3946 if (top < y)
3947 top = y;
3948 y = y_get(p_voice->staff, 0, 0, realwidth);
3949 if (bot > y)
3950 bot = y;
3951 }
3952 lyst_tb[staff].top = top;
3953 lyst_tb[staff].bot = bot;
3954 if (nly < 0)
3955 continue;
3956 nly++;
3957 lyvo_tb[voice].nly = nly;
3958 if (p_voice->posit.voc != 0)
3959 above_tb[voice] = p_voice->posit.voc == SL_ABOVE;
3960 else if (p_voice->next
3961 /*fixme:%%staves:KO - find an other way..*/
3962 && p_voice->next->staff == staff
3963 && p_voice->next->have_ly)
3964 above_tb[voice] = 1;
3965 if (above_tb[voice])
3966 lyst_tb[staff].a = 1;
3967 else
3968 lyst_tb[staff].b = 1;
3969 }
3970
3971 /* draw the lyrics under the staves */
3972 i = 0;
3973 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
3974 struct tblt_s *tblt;
3975
3976 if (!p_voice->sym)
3977 continue;
3978 if (!p_voice->have_ly
3979 && !p_voice->tblts[0])
3980 continue;
3981 voice = p_voice - voice_tb;
3982 if (above_tb[voice]) {
3983 rv_tb[i++] = voice;
3984 continue;
3985 }
3986 staff = p_voice->staff;
3987 if (lyvo_tb[voice].nly > 0)
3988 lyst_tb[staff].bot = draw_lyrics(p_voice, lyvo_tb[voice].nly,
3989 lyvo_tb[voice].h,
3990 lyst_tb[staff].bot, 1);
3991 sc = staff_tb[p_voice->staff].staffscale;
3992 for (nly = 0; nly < 2; nly++) {
3993 if ((tblt = p_voice->tblts[nly]) == NULL)
3994 break;
3995 // if (tblt->hu > 0) {
3996 // lyst_tb[staff].bot -= tblt->hu;
3997 // lyst_tb[staff].b = 1;
3998 // }
3999 if (tblt->pitch == 0)
4000 draw_tblt_w(p_voice,
4001 lyvo_tb[voice].nly,
4002 lyst_tb[staff].bot * sc - tblt->hu,
4003 tblt);
4004 else
4005 draw_tblt_p(p_voice,
4006 // lyst_tb[staff].bot,
4007 lyst_tb[staff].bot * sc - tblt->hu,
4008 tblt);
4009 if (tblt->hu > 0) {
4010 lyst_tb[staff].bot -= tblt->hu / sc;
4011 lyst_tb[staff].b = 1;
4012 }
4013 if (tblt->ha != 0) {
4014 lyst_tb[staff].top += tblt->ha / sc;
4015 lyst_tb[staff].a = 1;
4016 }
4017 }
4018 }
4019
4020 /* draw the lyrics above the staff */
4021 while (--i >= 0) {
4022 voice = rv_tb[i];
4023 p_voice = &voice_tb[voice];
4024 staff = p_voice->staff;
4025 lyst_tb[staff].top = draw_lyrics(p_voice, lyvo_tb[voice].nly,
4026 lyvo_tb[voice].h,
4027 lyst_tb[staff].top, -1);
4028 }
4029
4030 /* set the max y offsets of all symbols */
4031 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4032 if (!p_voice->sym)
4033 continue;
4034 staff = p_voice->staff;
4035 if (lyst_tb[staff].a) {
4036 top = lyst_tb[staff].top + 2;
4037 for (s = p_voice->sym; s; s = s->next) {
4038 /*fixme: may have lyrics crossing a next symbol*/
4039 if (s->ly) {
4040 /*fixme:should set the real width*/
4041 y_set(staff, 1, s->x - 2, 10, top);
4042 }
4043 }
4044 }
4045 if (lyst_tb[staff].b) {
4046 bot = lyst_tb[staff].bot - 2;
4047 if (lyvo_tb[p_voice - voice_tb].nly > 0) {
4048 for (s = p_voice->sym; s; s = s->next) {
4049 if (s->ly) {
4050 /*fixme:should set the real width*/
4051 y_set(staff, 0, s->x - 2, 10, bot);
4052 }
4053 }
4054 } else {
4055 y_set(staff, 0, 0, realwidth, bot);
4056 }
4057 }
4058 }
4059 }
4060
4061 /* -- draw the symbols near the notes -- */
4062 /* (the staves are not yet defined) */
4063 /* order:
4064 * - beams
4065 * - decorations near the notes
4066 * - measure bar numbers
4067 * - n-plets
4068 * - decorations tied to the notes
4069 * - slurs
4070 * - guitar chords
4071 * - then remaining decorations
4072 * The buffer output is delayed until the definition of the staff system,
4073 * so, global variables must be saved (see music.c delayed_output()).
4074 */
draw_sym_near(void)4075 void draw_sym_near(void)
4076 {
4077 struct VOICE_S *p_voice;
4078 struct SYMBOL *s, *g;
4079 int i, staff;
4080
4081 /* calculate the beams but don't draw them (the staves are not yet defined) */
4082 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4083 struct BEAM bm;
4084 int first_note = 1;
4085
4086 for (s = p_voice->sym; s; s = s->next) {
4087 for (g = s->extra; g; g = g->next) {
4088 if (g->type != NOTEREST)
4089 continue;
4090 if ((g->sflags & (S_BEAM_ST | S_BEAM_END))
4091 == S_BEAM_ST)
4092 calculate_beam(&bm, g);
4093 }
4094 if (s->abc_type != ABC_T_NOTE)
4095 continue;
4096 if (((s->sflags & S_BEAM_ST) && !(s->sflags & S_BEAM_END))
4097 || (first_note && !(s->sflags & S_BEAM_ST))) {
4098 first_note = 0;
4099 calculate_beam(&bm, s);
4100 }
4101 }
4102 }
4103
4104 /* initialize the y offsets */
4105 for (staff = 0; staff <= nstaff; staff++) {
4106 for (i = 0; i < YSTEP; i++) {
4107 staff_tb[staff].top[i] = 0;
4108 staff_tb[staff].bot[i] = 24;
4109 }
4110 }
4111
4112 set_tie_room();
4113 draw_deco_near();
4114
4115 /* set the min/max vertical offsets */
4116 for (s = tsfirst; s; s = s->ts_next) {
4117 int y;
4118
4119 if (s->flags & ABC_F_INVIS)
4120 continue;
4121 if (s->type == GRACE) {
4122 for (g = s->extra; g; g = g->next) {
4123 y_set(s->staff, 1, g->x - 2, 4,
4124 g->ymx + 1);
4125 y_set(s->staff, 0, g->x - 2, 4,
4126 g->ymn - 1);
4127 }
4128 continue;
4129 }
4130 if (s->type != MREST) {
4131 y_set(s->staff, 1, s->x - s->wl, s->wl + s->wr, s->ymx + 2);
4132 y_set(s->staff, 0, s->x - s->wl, s->wl + s->wr, s->ymn - 2);
4133 } else {
4134 y_set(s->staff, 1, s->x - 16, 32, s->ymx + 2);
4135 }
4136 if (s->abc_type != ABC_T_NOTE)
4137 continue;
4138
4139 /* have room for the accidentals */
4140 if (s->u.note.notes[s->nhd].acc) {
4141 y = s->y + 8;
4142 if (s->ymx < y)
4143 s->ymx = y;
4144 y_set(s->staff, 1, s->x, 0., y);
4145 }
4146 if (s->u.note.notes[0].acc) {
4147 y = s->y;
4148 if ((s->u.note.notes[0].acc & 0x07) == A_SH
4149 || s->u.note.notes[0].acc == A_NT)
4150 y -= 7;
4151 else
4152 y -= 5;
4153 if (s->ymn > y)
4154 s->ymn = y;
4155 y_set(s->staff, 0, s->x, 0., y);
4156 }
4157 }
4158
4159 if (cfmt.measurenb >= 0)
4160 draw_measnb();
4161
4162 // draw_deco_note();
4163
4164 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4165 s = p_voice->sym;
4166 if (!s)
4167 continue;
4168 //color
4169 set_color(s->color);
4170 set_sscale(p_voice->staff);
4171
4172 /* draw the tuplets near the notes */
4173 for ( ; s; s = s->next) {
4174 if (s->sflags & S_IN_TUPLET) {
4175 for (g = s->extra; g; g = g->next) {
4176 if (g->type == TUPLET) {
4177 s = draw_tuplet(g, s);
4178 break;
4179 }
4180 }
4181 }
4182 }
4183 draw_all_slurs(p_voice);
4184
4185 /* draw the tuplets over the slurs */
4186 for (s = p_voice->sym; s; s = s->next) {
4187 if (s->sflags & S_IN_TUPLET) {
4188 for (g = s->extra ; g; g = g->next) {
4189 if (g->type == TUPLET) {
4190 s = draw_tuplet(g, s);
4191 break;
4192 }
4193 }
4194 }
4195 }
4196 }
4197
4198 /* set the top and bottom for all symbols to be out of the staves */
4199 {
4200 int top, bot;
4201
4202 for (staff = 0; staff <= nstaff; staff++) {
4203 top = staff_tb[staff].topbar + 2;
4204 bot = staff_tb[staff].botbar - 2;
4205 for (i = 0; i < YSTEP; i++) {
4206 if (top > staff_tb[staff].top[i])
4207 staff_tb[staff].top[i] = (float) top;
4208 if (bot < staff_tb[staff].bot[i])
4209 staff_tb[staff].bot[i] = (float) bot;
4210 }
4211 }
4212 }
4213 set_color(0);
4214 draw_deco_note();
4215 draw_deco_staff();
4216 set_sscale(-1); /* restore the scale parameters */
4217 draw_all_lyrics();
4218 }
4219
4220 /* -- draw the name/subname of the voices -- */
draw_vname(float indent)4221 static void draw_vname(float indent)
4222 {
4223 struct VOICE_S *p_voice;
4224 int n, staff;
4225 struct {
4226 int nl;
4227 char *v[8];
4228 } staff_d[MAXSTAFF], *staff_p;
4229 char *p, *q;
4230 float y;
4231
4232 for (staff = cursys->nstaff; staff >= 0; staff--) {
4233 if (!cursys->staff[staff].empty)
4234 break;
4235 }
4236 if (staff < 0)
4237 return;
4238
4239 memset(staff_d, 0, sizeof staff_d);
4240 n = 0;
4241 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4242 if (!p_voice->sym)
4243 continue;
4244 staff = cursys->voice[p_voice - voice_tb].staff;
4245 if (cursys->staff[staff].empty)
4246 continue;
4247 if (p_voice->new_name) {
4248 p_voice->new_name = 0;
4249 p = p_voice->nm;
4250 } else {
4251 p = p_voice->snm;
4252 }
4253 if (!p)
4254 continue;
4255 if (cursys->staff[staff].flags & CLOSE_BRACE2) {
4256 while (!(cursys->staff[staff].flags & OPEN_BRACE2))
4257 staff--;
4258 } else if (cursys->staff[staff].flags & CLOSE_BRACE) {
4259 while (!(cursys->staff[staff].flags & OPEN_BRACE))
4260 staff--;
4261 }
4262 staff_p = &staff_d[staff];
4263 for (;;) {
4264 staff_p->v[staff_p->nl++] = p;
4265 p = strstr(p, "\\n");
4266 if (!p
4267 || staff_p->nl >= MAXSTAFF)
4268 break;
4269 p += 2;
4270 }
4271 n++;
4272 }
4273 if (n == 0)
4274 return;
4275 str_font(VOICEFONT);
4276 indent = -indent * .5; /* center */
4277 for (staff = nstaff; staff >= 0; staff--) {
4278 staff_p = &staff_d[staff];
4279 if (staff_p->nl == 0)
4280 continue;
4281 y = staff_tb[staff].y
4282 + staff_tb[staff].topbar * .5
4283 * staff_tb[staff].staffscale
4284 + 9 * (staff_p->nl - 1)
4285 - cfmt.font_tb[VOICEFONT].size * .3;
4286 n = staff;
4287 if (cursys->staff[staff].flags & OPEN_BRACE2) {
4288 while (!(cursys->staff[n].flags & CLOSE_BRACE2))
4289 n++;
4290 } else if (cursys->staff[staff].flags & OPEN_BRACE) {
4291 while (!(cursys->staff[n].flags & CLOSE_BRACE))
4292 n++;
4293 }
4294 if (n != staff)
4295 y -= (staff_tb[staff].y - staff_tb[n].y) * .5;
4296 for (n = 0; n < staff_p->nl; n++) {
4297 p = staff_p->v[n];
4298 q = strstr(p, "\\n");
4299 if (q)
4300 *q = '\0';
4301 a2b("%.1f %.1f M ", indent, y);
4302 put_str(p, A_CENTER);
4303 y -= 18.;
4304 if (q)
4305 *q = '\\';
4306 }
4307 }
4308 }
4309
4310 /* -- set the y offset of the staves and return the whole height -- */
set_staff(void)4311 static float set_staff(void)
4312 {
4313 struct SYSTEM *sy;
4314 struct SYMBOL *s;
4315 int i, staff, prev_staff;
4316 float y, staffsep, dy, maxsep, mbot, v;
4317 char empty[MAXSTAFF];
4318
4319 /* search the empty staves in each parts */
4320 memset(empty, 1, sizeof empty);
4321 for (staff = 0; staff <= nstaff; staff++)
4322 staff_tb[staff].empty = 0;
4323 sy = cursys;
4324 for (staff = 0; staff <= nstaff; staff++) {
4325 if (!sy->staff[staff].empty)
4326 empty[staff] = 0;
4327 }
4328 for (s = tsfirst; s; s = s->ts_next) {
4329 if (!(s->sflags & S_NEW_SY))
4330 continue;
4331 sy = sy->next;
4332 for (staff = 0; staff <= nstaff; staff++) {
4333 if (!sy->staff[staff].empty)
4334 empty[staff] = 0;
4335 }
4336 }
4337
4338 /* output the scale of the voices
4339 * and flag as non empty the staves with tablatures */
4340 {
4341 struct VOICE_S *p_voice;
4342
4343 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4344 if (p_voice->scale != 1)
4345 a2b("/scvo%d{gsave %.2f dup scale}!\n",
4346 (int) (p_voice - voice_tb),
4347 p_voice->scale);
4348 if (p_voice->tblts[0])
4349 empty[p_voice->staff] = 0;
4350 }
4351 }
4352
4353 /* set the vertical offset of the 1st staff */
4354 for (staff = 0; staff <= nstaff; staff++) {
4355 if (!empty[staff])
4356 break;
4357 staff_tb[staff].empty = 1;
4358 }
4359 y = 0;
4360 if (staff > nstaff) {
4361 staff--; /* one staff, empty */
4362 } else {
4363 for (i = 0; i < YSTEP; i++) {
4364 v = staff_tb[staff].top[i];
4365 if (y < v)
4366 y = v;
4367 }
4368 }
4369
4370 /* draw the parts and tempo indications if any */
4371 y += draw_partempo(staff, y);
4372
4373 if (empty[staff])
4374 return y;
4375
4376 y *= staff_tb[staff].staffscale;
4377 staffsep = cfmt.staffsep * 0.5 +
4378 staff_tb[staff].topbar * staff_tb[staff].staffscale;
4379 if (y < staffsep)
4380 y = staffsep;
4381 staff_tb[staff].y = -y;
4382
4383 /* set the offset of the other staves */
4384 prev_staff = staff;
4385 for (staff++; staff <= nstaff; staff++) {
4386 if (empty[staff]) {
4387 staff_tb[staff].empty = 1;
4388 continue;
4389 }
4390 if (sy->staff[prev_staff].sep != 0)
4391 staffsep = sy->staff[prev_staff].sep;
4392 else
4393 staffsep = cfmt.sysstaffsep;
4394 if (sy->staff[prev_staff].maxsep != 0)
4395 maxsep = sy->staff[prev_staff].maxsep;
4396 else
4397 maxsep = cfmt.maxsysstaffsep;
4398
4399 dy = 0;
4400 if (staff_tb[staff].staffscale
4401 == staff_tb[prev_staff].staffscale) {
4402 for (i = 0; i < YSTEP; i++) {
4403 v = staff_tb[staff].top[i]
4404 - staff_tb[prev_staff].bot[i];
4405 if (dy < v)
4406 dy = v;
4407 }
4408 dy *= staff_tb[staff].staffscale;
4409 } else {
4410 for (i = 0; i < YSTEP; i++) {
4411 v = staff_tb[staff].top[i]
4412 * staff_tb[staff].staffscale
4413 - staff_tb[prev_staff].bot[i]
4414 * staff_tb[prev_staff].staffscale;
4415 if (dy < v)
4416 dy = v;
4417 }
4418 }
4419 staffsep += staff_tb[staff].topbar
4420 * staff_tb[staff].staffscale;
4421 if (dy < staffsep)
4422 dy = staffsep;
4423 maxsep += staff_tb[staff].topbar
4424 * staff_tb[staff].staffscale;
4425 if (dy > maxsep)
4426 dy = maxsep;
4427 y += dy;
4428 staff_tb[staff].y = -y;
4429
4430 prev_staff = staff;
4431 }
4432 mbot = 0;
4433 for (i = 0; i < YSTEP; i++) {
4434 v = staff_tb[prev_staff].bot[i];
4435 if (mbot > v)
4436 mbot = v;
4437 }
4438 mbot *= staff_tb[prev_staff].staffscale;
4439
4440 /* output the staff offsets */
4441 for (staff = nstaff; staff >= 0; staff--) {
4442 dy = staff_tb[staff].y;
4443 if (staff_tb[staff].staffscale != 1
4444 && staff_tb[staff].staffscale != 0) {
4445 a2b("/scst%d{gsave 0 %.2f T %.2f dup scale}!\n",
4446 staff, dy, staff_tb[staff].staffscale);
4447 a2b("/y%d{}!\n", staff);
4448 } else {
4449 a2b("/y%d{%.1f add}!\n", staff, dy);
4450 }
4451 a2b("/yns%d{%.1f add}!\n", staff, dy);
4452 }
4453
4454 if (mbot == 0) {
4455 for (staff = nstaff; staff >= 0; staff--) {
4456 if (!empty[staff])
4457 break;
4458 }
4459 if (staff < 0) /* no symbol in this system ! */
4460 return y;
4461 }
4462 dy = -mbot;
4463 staffsep = cfmt.staffsep * 0.5;
4464 if (dy < staffsep)
4465 dy = staffsep;
4466 maxsep = cfmt.maxstaffsep * 0.5;
4467 if (dy > maxsep)
4468 dy = maxsep;
4469
4470 /* return the whole staff system height */
4471 return y + dy;
4472 }
4473
4474 /* -- set the bottom and height of the measure bars -- */
bar_set(float * bar_bot,float * bar_height,float * xstaff)4475 static void bar_set(float *bar_bot, float *bar_height, float *xstaff)
4476 {
4477 int staff;
4478 float dy, staffscale, top, bot;
4479
4480 dy = 0;
4481 for (staff = 0; staff <= cursys->nstaff; staff++) {
4482 // if (cursys->staff[staff].empty) {
4483 if (xstaff[staff] < 0) {
4484 bar_bot[staff] = bar_height[staff] = 0;
4485 continue;
4486 }
4487 staffscale = staff_tb[staff].staffscale;
4488 top = staff_tb[staff].topbar * staffscale;
4489 bot = staff_tb[staff].botbar * staffscale;
4490 if (dy == 0)
4491 dy = staff_tb[staff].y + top;
4492 bar_bot[staff] = staff_tb[staff].y + bot;
4493 bar_height[staff] = dy - bar_bot[staff];
4494
4495 if (cursys->staff[staff].flags & STOP_BAR)
4496 dy = 0;
4497 else
4498 dy = bar_bot[staff];
4499 }
4500 }
4501
4502 /* -- draw the staff systems and the measure bars -- */
draw_systems(float indent)4503 float draw_systems(float indent)
4504 {
4505 struct SYMBOL *s, *s2;
4506 int staff, bar_force;
4507 float xstaff[MAXSTAFF], bar_bot[MAXSTAFF], bar_height[MAXSTAFF];
4508 float staves_bar, x, x2, line_height;
4509
4510 line_height = set_staff();
4511 draw_vname(indent);
4512
4513 /* draw the staff, skipping the staff breaks */
4514 for (staff = 0; staff <= nstaff; staff++)
4515 xstaff[staff] = cursys->staff[staff].empty ? -1 : 0;
4516 bar_set(bar_bot, bar_height, xstaff);
4517 draw_lstaff(0);
4518 bar_force = 0;
4519 for (s = tsfirst; s; s = s->ts_next) {
4520 if (bar_force && s->time != bar_force) {
4521 bar_force = 0;
4522 for (staff = 0; staff <= nstaff; staff++) {
4523 if (cursys->staff[staff].empty)
4524 xstaff[staff] = -1;
4525 }
4526 bar_set(bar_bot, bar_height, xstaff);
4527 }
4528 if (s->sflags & S_NEW_SY) {
4529 staves_bar = 0;
4530 for (s2 = s; s2; s2 = s2->ts_next) {
4531 if (s2->time != s->time)
4532 break;
4533 if (s2->type == BAR) {
4534 staves_bar = s2->x;
4535 break;
4536 }
4537 }
4538 cursys = cursys->next;
4539 for (staff = 0; staff <= nstaff; staff++) {
4540 x = xstaff[staff];
4541 if (x < 0) { // no staff yet
4542 if (!cursys->staff[staff].empty) {
4543 if (staves_bar != 0)
4544 xstaff[staff] = staves_bar;
4545 else
4546 xstaff[staff] = s->x - s->wl - 2;
4547 }
4548 continue;
4549 }
4550 if (!cursys->staff[staff].empty) // if not staff stop
4551 continue;
4552 if (staves_bar != 0) {
4553 x2 = staves_bar;
4554 bar_force = s->time;
4555 } else {
4556 x2 = s->x - s->wl - 2;
4557 xstaff[staff] = -1;
4558 }
4559 draw_staff(staff, x, x2);
4560 }
4561 bar_set(bar_bot, bar_height, xstaff);
4562 }
4563 staff = s->staff;
4564 switch (s->type) {
4565 case BAR:
4566 if ((s->sflags & S_SECOND)
4567 // || cursys->staff[staff].empty)
4568 || xstaff[staff] < 0)
4569 s->flags |= ABC_F_INVIS;
4570 if (s->flags & ABC_F_INVIS)
4571 break;
4572 draw_bar(s, bar_bot[staff], bar_height[staff]);
4573 if (annotate)
4574 anno_out(s, 'B');
4575 break;
4576 case STBRK:
4577 if (cursys->voice[s->voice].range == 0) {
4578 if (s->xmx > .5 CM) {
4579 int i, nvoice;
4580
4581 /* draw the left system if stbrk in all voices */
4582 nvoice = 0;
4583 for (i = 0; i < MAXVOICE; i++) {
4584 if (cursys->voice[i].range > 0)
4585 nvoice++;
4586 }
4587 for (s2 = s->ts_next; s2; s2 = s2->ts_next) {
4588 if (s2->type != STBRK)
4589 break;
4590 nvoice--;
4591 }
4592 if (nvoice == 0)
4593 draw_lstaff(s->x);
4594 }
4595 }
4596 s2 = s->prev;
4597 if (!s2)
4598 break;
4599 x2 = s2->x;
4600 if (s2->type != BAR)
4601 x2 += s2->wr;
4602 staff = s->staff;
4603 x = xstaff[staff];
4604 if (x >= 0) {
4605 if (x >= x2)
4606 continue;
4607 draw_staff(staff, x, x2);
4608 }
4609 xstaff[staff] = s->x;
4610 break;
4611 default:
4612 //fixme:does not work for "%%staves K: M: $" */
4613 //removed for K:/M: in empty staves
4614 // if (cursys->staff[staff].empty)
4615 // s->flags |= ABC_F_INVIS;
4616 break;
4617 }
4618 }
4619
4620 // draw the end of the staves
4621 for (staff = 0; staff <= nstaff; staff++) {
4622 if (bar_force && cursys->staff[staff].empty)
4623 continue;
4624 if ((x = xstaff[staff]) < 0)
4625 continue;
4626 draw_staff(staff, x, realwidth);
4627 }
4628 set_sscale(-1);
4629 return line_height;
4630 }
4631
4632 /* -- output PostScript sequences and set the staff and voice colors -- */
output_ps(struct SYMBOL * s,int color)4633 void output_ps(struct SYMBOL *s, int color)
4634 {
4635 struct SYMBOL *g, *g2;
4636
4637 g = s->extra;
4638 g2 = NULL;
4639 for ( ; g; g = g->next) {
4640 if (g->type == FMTCHG) {
4641 switch (g->aux) {
4642 case PSSEQ:
4643 // case SVGSEQ:
4644 // if (g->aux == SVGSEQ)
4645 // a2b("%%svg %s\n", g->text);
4646 // else
4647 a2b("%s\n", g->text);
4648 if (!g2)
4649 s->extra = g->next;
4650 else
4651 g2->next = g->next;
4652 continue;
4653 }
4654 }
4655 g2 = g;
4656 }
4657 }
4658
4659 /* -- draw remaining symbols when the staves are defined -- */
draw_symbols(struct VOICE_S * p_voice)4660 static void draw_symbols(struct VOICE_S *p_voice)
4661 {
4662 struct BEAM bm;
4663 struct SYMBOL *s;
4664 float x, y;
4665 int staff, first_note;
4666
4667 #if 0
4668 /* output the PostScript code at start of line */
4669 for (s = p_voice->sym; s; s = s->next) {
4670 if (s->extra)
4671 output_ps(s, 1);
4672 switch (s->type) {
4673 case CLEF:
4674 case KEYSIG:
4675 case TIMESIG:
4676 case BAR:
4677 continue; /* skip the symbols added by init_music_line() */
4678 }
4679 break;
4680 }
4681 #endif
4682
4683 bm.s2 = NULL;
4684 first_note = 1;
4685 for (s = p_voice->sym; s; s = s->next) {
4686 if (s->extra)
4687 output_ps(s, 1);
4688 if (s->flags & ABC_F_INVIS) {
4689 switch (s->type) {
4690 case KEYSIG:
4691 memcpy(&p_voice->key, &s->u.key,
4692 sizeof p_voice->key);
4693 default:
4694 continue;
4695 case NOTEREST:
4696 case GRACE:
4697 break;
4698 }
4699 }
4700 set_color(s->color);
4701 x = s->x;
4702 switch (s->type) {
4703 case NOTEREST:
4704 set_scale(s);
4705 if (s->abc_type == ABC_T_NOTE) {
4706 if ((s->sflags & (S_BEAM_ST | S_BEAM_END)) == S_BEAM_ST
4707 || (first_note && !(s->sflags & S_BEAM_ST))) {
4708 first_note = 0;
4709 if (calculate_beam(&bm, s)) {
4710 if (annotate)
4711 anno_out(s, 'b');
4712 draw_beams(&bm);
4713 }
4714 }
4715 draw_note(x, s, bm.s2 == NULL);
4716 if (annotate)
4717 anno_out(s, 'N');
4718 if (s == bm.s2)
4719 bm.s2 = NULL;
4720 if (annotate
4721 && (s->sflags & (S_BEAM_ST | S_BEAM_END))
4722 == S_BEAM_END)
4723 anno_out(s, 'e');
4724 break;
4725 }
4726 draw_rest(s);
4727 if (annotate)
4728 anno_out(s, 'R');
4729 break;
4730 case BAR:
4731 break; /* drawn in draw_systems */
4732 case CLEF:
4733 staff = s->staff;
4734 if (s->sflags & S_SECOND)
4735 /* || p_voice->staff != staff) */
4736 break; /* only one clef per staff */
4737 if ((s->flags & ABC_F_INVIS)
4738 || staff_tb[staff].empty)
4739 break;
4740 set_color(0);
4741 set_sscale(staff);
4742 y = staff_tb[staff].y;
4743 x -= 10; /* clef shift - see set_width() */
4744 putxy(x, y + s->y);
4745 if (s->u.clef.name)
4746 a2b("%s\n", s->u.clef.name);
4747 else
4748 a2b("%c%cclef\n",
4749 s->aux ? 's' : ' ',
4750 "tcbp"[(unsigned) s->u.clef.type]);
4751 if (s->u.clef.octave != 0) {
4752 /*fixme:break the compatibility and avoid strange numbers*/
4753 if (s->u.clef.octave > 0)
4754 y += s->ymx - 9;
4755 else
4756 y += s->ymn;
4757 putxy(x - 2, y);
4758 a2b("oct\n");
4759 }
4760 if (annotate)
4761 anno_out(s, 'c');
4762 break;
4763 case TIMESIG:
4764 //fixme: set staff color
4765 memcpy(&p_voice->meter, &s->u.meter,
4766 sizeof p_voice->meter);
4767 if ((s->sflags & S_SECOND)
4768 || staff_tb[s->staff].empty)
4769 break;
4770 if (cfmt.alignbars && s->staff != 0)
4771 break;
4772 set_color(0);
4773 set_sscale(s->staff);
4774 draw_timesig(x, s);
4775 if (annotate)
4776 anno_out(s, 'M');
4777 break;
4778 case KEYSIG:
4779 //fixme: set staff color
4780 memcpy(&p_voice->key, &s->u.key,
4781 sizeof p_voice->key);
4782 if ((s->sflags & S_SECOND)
4783 || staff_tb[s->staff].empty)
4784 break;
4785 set_color(0);
4786 set_sscale(s->staff);
4787 draw_keysig(p_voice, x, s);
4788 if (annotate)
4789 anno_out(s, 'K');
4790 break;
4791 case MREST:
4792 set_scale(s);
4793 putxy(x, staff_tb[s->staff].y + 12);
4794 a2b("mrest(%d)/Times-Bold 15 selectfont ",
4795 s->u.bar.len);
4796 putxy(x, staff_tb[s->staff].y + 28);
4797 a2b("M showc\n");
4798 if (annotate)
4799 anno_out(s, 'Z');
4800 break;
4801 case GRACE:
4802 set_scale(s);
4803 draw_gracenotes(s);
4804 break;
4805 case SPACE:
4806 case STBRK:
4807 case FMTCHG:
4808 break; /* nothing */
4809 case CUSTOS:
4810 set_scale(s);
4811 s->sflags |= ABC_F_STEMLESS;
4812 draw_note(x, s, 0);
4813 break;
4814 default:
4815 bug("Symbol not drawn", 1);
4816 }
4817 }
4818 set_scale(p_voice->sym);
4819 draw_all_ties(p_voice);
4820 set_sscale(-1);
4821 set_color(0);
4822 }
4823
4824 /* -- draw all symbols -- */
draw_all_symb(void)4825 void draw_all_symb(void)
4826 {
4827 struct VOICE_S *p_voice;
4828 struct SYMBOL *s;
4829
4830 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
4831 #if 1 /* pb about rest display when "%%staffnonote 0" fixed in draw_rest */
4832 if (p_voice->sym)
4833 #else
4834 if (p_voice->sym
4835 && !staff_tb[p_voice->staff].empty)
4836 #endif
4837 draw_symbols(p_voice);
4838 }
4839
4840 // update the clefs
4841 for (s = tsfirst; s; s = s->ts_next) {
4842 if (s->type == CLEF)
4843 staff_tb[s->staff].s_clef = s;
4844 }
4845 }
4846
4847 /* -- output a floating value, and x and y according to the current scale -- */
putf(float v)4848 void putf(float v)
4849 {
4850 a2b("%.1f ", v);
4851 }
4852
putx(float x)4853 void putx(float x)
4854 {
4855 putf(x / cur_scale);
4856 }
4857
puty(float y)4858 void puty(float y)
4859 {
4860 putf(scale_voice ?
4861 y / cur_scale : /* scaled voice */
4862 y - cur_trans); /* scaled staff */
4863 }
4864
putxy(float x,float y)4865 void putxy(float x, float y)
4866 {
4867 if (scale_voice)
4868 a2b("%.1f %.1f ",
4869 x / cur_scale, y / cur_scale); /* scaled voice */
4870 else
4871 a2b("%.1f %.1f ",
4872 x / cur_scale, y - cur_trans); /* scaled staff */
4873 }
4874
4875 /* -- set the voice or staff scale -- */
set_scale(struct SYMBOL * s)4876 void set_scale(struct SYMBOL *s)
4877 {
4878 float scale, trans;
4879
4880 scale = voice_tb[s->voice].scale;
4881 if (scale == 1) {
4882 set_sscale(s->staff);
4883 return;
4884 }
4885 /*fixme: KO when both staff and voice are scaled */
4886 trans = 0;
4887 scale_voice = 1;
4888 if (scale == cur_scale && trans == cur_trans)
4889 return;
4890 if (cur_scale != 1)
4891 a2b("grestore ");
4892 cur_scale = scale;
4893 cur_trans = trans;
4894 if (scale != 1)
4895 a2b("scvo%d ", s->voice);
4896 }
4897
4898 /* -- set the staff scale (only) -- */
set_sscale(int staff)4899 void set_sscale(int staff)
4900 {
4901 float scale, trans;
4902
4903 scale_voice = 0;
4904 if (staff != cur_staff && cur_scale != 1)
4905 cur_scale = 0;
4906 if (staff >= 0)
4907 scale = staff_tb[staff].staffscale;
4908 else
4909 scale = 1;
4910 if (staff >= 0 && scale != 1)
4911 trans = staff_tb[staff].y;
4912 else
4913 trans = 0;
4914 if (scale == cur_scale && trans == cur_trans)
4915 return;
4916 if (cur_scale != 1)
4917 a2b("grestore ");
4918 cur_scale = scale;
4919 cur_trans = trans;
4920 if (scale != 1) {
4921 a2b("scst%d ", staff);
4922 cur_staff = staff;
4923 }
4924 }
4925
4926 /* -- set the tie directions for one voice -- */
set_tie_dir(struct SYMBOL * sym)4927 static void set_tie_dir(struct SYMBOL *sym)
4928 {
4929 struct SYMBOL *s;
4930 int i, ntie, dir, sec, pit, ti;
4931
4932 for (s = sym; s; s = s->next) {
4933 if (!(s->sflags & S_TI1))
4934 continue;
4935
4936 /* if other voice, set the ties in opposite direction */
4937 if (s->multi != 0) {
4938 /* struct SYMBOL *s2;
4939
4940 s2 = s->ts_next;
4941 if (s2->time == s->time && s2->staff == s->staff) { */
4942 dir = s->multi > 0 ? SL_ABOVE : SL_BELOW;
4943 for (i = 0; i <= s->nhd; i++) {
4944 ti = s->u.note.notes[i].ti1;
4945 if (!((ti & 0x07) == SL_AUTO))
4946 continue;
4947 s->u.note.notes[i].ti1 = (ti & SL_DOTTED) | dir;
4948 }
4949 continue;
4950 /* } */
4951 }
4952
4953 /* if one note, set the direction according to the stem */
4954 sec = ntie = 0;
4955 pit = 128;
4956 for (i = 0; i <= s->nhd; i++) {
4957 if (s->u.note.notes[i].ti1) {
4958 ntie++;
4959 if (pit < 128
4960 && s->u.note.notes[i].pit <= pit + 1)
4961 sec++;
4962 pit = s->u.note.notes[i].pit;
4963 }
4964 }
4965 if (ntie <= 1) {
4966 dir = s->stem < 0 ? SL_ABOVE : SL_BELOW;
4967 for (i = 0; i <= s->nhd; i++) {
4968 ti = s->u.note.notes[i].ti1;
4969 if (ti != 0) {
4970 if ((ti & 0x07) == SL_AUTO)
4971 s->u.note.notes[i].ti1 =
4972 (ti & SL_DOTTED) | dir;
4973 break;
4974 }
4975 }
4976 continue;
4977 }
4978 if (sec == 0) {
4979 if (ntie & 1) {
4980 /* in chords with an odd number of notes, the outer noteheads are paired off
4981 * center notes are tied according to their position in relation to the
4982 * center line */
4983 ntie /= 2;
4984 dir = SL_BELOW;
4985 for (i = 0; i <= s->nhd; i++) {
4986 ti = s->u.note.notes[i].ti1;
4987 if (ti == 0)
4988 continue;
4989 if (ntie == 0) { /* central tie */
4990 if (s->pits[i] >= 22)
4991 dir = SL_ABOVE;
4992 }
4993 if ((ti & 0x07) == SL_AUTO)
4994 s->u.note.notes[i].ti1 =
4995 (ti & SL_DOTTED) | dir;
4996 if (ntie-- == 0)
4997 dir = SL_ABOVE;
4998 }
4999 continue;
5000 }
5001 /* even number of notes, ties divided in opposite directions */
5002 ntie /= 2;
5003 dir = SL_BELOW;
5004 for (i = 0; i <= s->nhd; i++) {
5005 ti = s->u.note.notes[i].ti1;
5006 if (ti == 0)
5007 continue;
5008 if ((ti & 0x07) == SL_AUTO)
5009 s->u.note.notes[i].ti1 =
5010 (ti & SL_DOTTED) | dir;
5011 if (--ntie == 0)
5012 dir = SL_ABOVE;
5013 }
5014 continue;
5015 }
5016 /*fixme: treat more than one second */
5017 /* if (nsec == 1) { */
5018 /* When a chord contains the interval of a second, tie those two notes in
5019 * opposition; then fill in the remaining notes of the chord accordingly */
5020 pit = 128;
5021 for (i = 0; i <= s->nhd; i++) {
5022 if (s->u.note.notes[i].ti1) {
5023 if (pit < 128
5024 && s->u.note.notes[i].pit <= pit + 1) {
5025 ntie = i;
5026 break;
5027 }
5028 pit = s->u.note.notes[i].pit;
5029 }
5030 }
5031 dir = SL_BELOW;
5032 for (i = 0; i <= s->nhd; i++) {
5033 ti = s->u.note.notes[i].ti1;
5034 if (ti == 0)
5035 continue;
5036 if (ntie == i)
5037 dir = SL_ABOVE;
5038 if ((ti & 0x07) == SL_AUTO)
5039 s->u.note.notes[i].ti1 =
5040 (ti & SL_DOTTED) | dir;
5041 }
5042 /*fixme..
5043 continue;
5044 }
5045 ..*/
5046 /* if a chord contains more than one pair of seconds, the pair farthest
5047 * from the center line receives the ties drawn in opposition */
5048 }
5049 }
5050
5051 /* -- have room for the ties out of the staves -- */
set_tie_room(void)5052 static void set_tie_room(void)
5053 {
5054 struct VOICE_S *p_voice;
5055 struct SYMBOL *s, *s2;
5056
5057 for (p_voice = first_voice; p_voice; p_voice = p_voice->next) {
5058 s = p_voice->sym;
5059 if (!s)
5060 continue;
5061 s = s->next;
5062 if (!s)
5063 continue;
5064 set_tie_dir(s);
5065 for ( ; s; s = s->next) {
5066 float dx, y, dy;
5067
5068 if (!(s->sflags & S_TI1))
5069 continue;
5070 if (s->pits[0] < 20
5071 && (s->u.note.notes[0].ti1 & 0x07) == SL_BELOW)
5072 ;
5073 else if (s->pits[s->nhd] > 24
5074 && (s->u.note.notes[s->nhd].ti1 & 0x07) == SL_ABOVE)
5075 ;
5076 else
5077 continue;
5078 s2 = s->next;
5079 while (s2 && s2->abc_type != ABC_T_NOTE)
5080 s2 = s2->next;
5081 if (s2) {
5082 if (s2->staff != s->staff)
5083 continue;
5084 dx = s2->x - s->x - 10;
5085 } else {
5086 dx = realwidth - s->x - 10;
5087 }
5088 if (dx < 100)
5089 dy = 9;
5090 else if (dx < 300)
5091 dy = 12;
5092 else
5093 dy = 16;
5094 if (s->pits[s->nhd] > 24) {
5095 y = 3 * (s->pits[s->nhd] - 18) + dy;
5096 if (s->ymx < y)
5097 s->ymx = y;
5098 if (s2 && s2->ymx < y)
5099 s2->ymx = y;
5100 y_set(s->staff, 1, s->x + 5, dx, y);
5101 }
5102 if (s->pits[0] < 20) {
5103 y = 3 * (s->pits[0] - 18) - dy;
5104 if (s->ymn > y)
5105 s->ymn = y;
5106 if (s2 && s2->ymn > y)
5107 s2->ymn = y;
5108 y_set(s->staff, 0, s->x + 5, dx, y);
5109 }
5110 }
5111 }
5112 }
5113