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