1 /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
2 /* All rights reserved */
6 * Description: This file contains functions for setting the relative
7 * horizontal and vertical coordinates of all groups that
8 * contain a rest or space (grpcont != GC_NOTES), and the relative
9 * horizontal coordinates of syllables. It then completes
10 * the relative horizontal work by setting the relative
11 * horizontal coords of chords. But before it does that last
12 * step, it scales all the relative coords set so far according
25 static double highcoord
P((struct GRPSYL
*gs_p
, struct GRPSYL
*altgs_p
));
26 static double lowcoord
P((struct GRPSYL
*gs_p
, struct GRPSYL
*altgs_p
));
27 static void procrests
P((struct CHORD
*ch_p
, struct STAFF
*staff_p
,
28 struct GRPSYL
*gs_p
, double limhigh
, double limlow
));
29 static void procspaces
P((struct GRPSYL
*gs_p
));
30 static struct GRPSYL
*finalgroupproc
P((struct GRPSYL
*gs1_p
));
31 static int v3pack
P((struct GRPSYL
*g_p
[], int numgrps
));
32 static void fixclef
P((struct GRPSYL
*gs1_p
));
33 static void restsize
P((struct GRPSYL
*gs_p
, float *wid_p
, float *asc_p
,
35 static void procsyls
P((struct GRPSYL
*gs_p
));
36 static void apply_staffscale
P((void));
37 static void relxchord
P((void));
38 static double effwest
P((struct MAINLL
*mainll_p
, struct CHORD
*ch_p
,
39 struct GRPSYL
*gs_p
));
40 static double effeast
P((struct CHORD
*ch_p
, struct GRPSYL
*gs_p
));
41 static int collision_danger
P((struct GRPSYL
*g1_p
, struct GRPSYL
*g2_p
));
42 static struct CHORD
*prevchord
P((struct MAINLL
*mainll_p
, struct CHORD
*ch_p
));
43 static struct GRPSYL
*nextchsyl
P((struct GRPSYL
*gs_p
, struct CHORD
*ch_p
));
44 static struct GRPSYL
*prevchsyl
P((struct GRPSYL
*gs_p
,
45 struct CHORD
*prevch_p
));
46 static void pedalroom
P((void));
47 static struct CHORD
*closestchord
P((double count
, struct CHORD
*firstch_p
));
48 static double rightped
P((int pedstyle
, int pedchar
));
49 static double leftped
P((int pedstyle
, int pedchar
));
50 static void fixspace
P((void));
55 * Abstract: Sets all relative coords for rests and spaces, and horizontal
56 * ones for syllables; set relative horz. coords of chords.
60 * Description: This function loops through the main linked list, finding every
61 * STAFF structure. For groups, it calls procrests() to process
62 * every rest in the linked list, and procspaces() to process
63 * every space in the linked list. For syllables, it calls
64 * procsyls(). At the end it calls apply_staffscale() to apply
65 * staffscale to all the relative coords set so far, and then
66 * relxchord() to set the relative horizontal coords of chords.
73 register struct MAINLL
*mainll_p
; /* point item in main linked list */
74 struct MAINLL
*mll_p
; /* another MLL pointer */
75 struct STAFF
*staff_p
; /* point at a staff */
76 struct STAFF
*stafflist
[MAXSTAFFS
+ 1]; /* point to this meas's staffs*/
77 float limhigh
[MAXSTAFFS
+ 1]; /* high y coord of limit of groups */
78 float limlow
[MAXSTAFFS
+ 1]; /* low y coord of limit of groups */
79 int vscheme
; /* voice scheme */
80 int v
; /* index into verse headcell array */
81 struct CHORD
*ch_p
; /* point at a chord */
82 struct GRPSYL
*gs1_p
; /* point at a group */
90 * Loop down the main linked list looking for each chord list
93 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
95 if (mainll_p
->str
== S_SSV
) {
96 asgnssv(mainll_p
->u
.ssv_p
);
100 if (mainll_p
->str
!= S_CHHEAD
)
101 continue; /* skip everything but chord HC */
104 * For each visible staff in this measure, find the high and
105 * low limits of the relevant voices, so that we know what to
106 * avoid when placing rests in other voices.
108 for (mll_p
= mainll_p
->next
; mll_p
->str
== S_STAFF
;
109 mll_p
= mll_p
->next
) {
111 staff_p
= mll_p
->u
.staff_p
;
112 stafflist
[staff_p
->staffno
] = staff_p
;
113 vscheme
= svpath(staff_p
->staffno
, VSCHEME
)->vscheme
;
114 if (staff_p
->visible
== NO
) {
119 * If there is more than one voice, each voice's rests
120 * have to worry about avoiding other voices' notes.
121 * So find how high voice 2 and how low voice 1, get,
122 * in this measure. But voice 3 can "stand in" for
123 * either, so pass that in too. If it's null, that's
124 * okay, the subroutines handle that.
126 if (vscheme
!= V_1
) {
127 limhigh
[staff_p
->staffno
] =
128 highcoord(staff_p
->groups_p
[1],
129 staff_p
->groups_p
[2]);
130 limlow
[staff_p
->staffno
] =
131 lowcoord(staff_p
->groups_p
[0],
132 staff_p
->groups_p
[2]);
134 /* prevent uninitialized var, though not used*/
135 limhigh
[staff_p
->staffno
] = 0;
136 limlow
[staff_p
->staffno
] = 0;
141 * Loop through each chord in this list.
143 for (ch_p
= mainll_p
->u
.chhead_p
->ch_p
; ch_p
!= 0;
146 * Loop through the linked list of GRPSYLs hanging off
147 * this chord. Skip the syllables; just deal with the
148 * groups. Upon finding the first group on a staff
149 * (which could be for any of the voices, since not all
150 * might be present in this chord), call procrests and
151 * finalgroupproc to process the groups.
155 /* find first group on a staff */
157 gs1_p
->grpsyl
== GS_SYLLABLE
)
163 * Call procrests() to place any rest in the
164 * voice on this staff in this chord.
166 procrests(ch_p
, stafflist
[gs1_p
->staffno
],
167 gs1_p
, limhigh
[gs1_p
->staffno
],
168 limlow
[gs1_p
->staffno
]);
170 /* set gs1_p to after this staff's groups */
171 gs1_p
= finalgroupproc(gs1_p
);
179 * Loop once for each item in the main linked list. Now that we're all
180 * done with notes and rests, do the spaces and syllables.
182 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
184 if (mainll_p
->str
== S_SSV
) {
186 asgnssv(mainll_p
->u
.ssv_p
);
188 } else if (mainll_p
->str
== S_STAFF
&&
189 mainll_p
->u
.staff_p
->visible
== YES
) {
191 /* for each voice that exists, process the spaces */
192 for (v
= 0; v
< MAXVOICES
; v
++) {
193 if (mainll_p
->u
.staff_p
->groups_p
[v
] != 0) {
194 procspaces(mainll_p
->u
.staff_p
->
199 /* set relative horizontal coords for syllables */
200 for (v
= 0; v
< mainll_p
->u
.staff_p
->nsyllists
; v
++) {
201 procsyls(mainll_p
->u
.staff_p
->syls_p
[v
]);
206 /* scale all relative coords set so far according to staffscale */
209 /* now we are ready to set relative horizontal coords for all chords */
216 * Abstract: Find highest relative y coord of a group in one GRPSYL list.
220 * Description: This function goes down one of the linked lists of GRPSYLs,
221 * one that is for groups, not syllables, and finds the highest
222 * relative y coordinate of any group containing notes. If there
223 * are no notes but there are rests, it returns 0. If there are
224 * only spaces, it returns -100. The answer, though, is rounded
225 * off to the nearest staff line. Besides the primary linked list
226 * of GRPSYLs, it also looks for GRPSYLs in the alternate list
227 * (voice 3 if it exists) and considers ones that are "standing in"
228 * for the first list's voice.
232 highcoord(gs_p
, altgs_p
)
234 register struct GRPSYL
*gs_p
; /* starts pointing at first GRPSYL in list */
235 register struct GRPSYL
*altgs_p
;/* first GRPSYL of voice 3, if any */
239 int normvoice
; /* main voice we are dealing with, 1 or 2 */
240 float edge
; /* of a group in the other voice */
243 debug(32, "highcoord file=%s line=%d", gs_p
->inputfile
,
245 result
= -100; /* init as if only spaces */
246 normvoice
= gs_p
->vno
; /* remember the voice we're dealing with */
249 * Loop through all groups (even grace), moving result up when
250 * something higher is found. Rests count as 0 (the middle line).
252 for ( ; gs_p
!= 0; gs_p
= gs_p
->next
) {
253 switch (gs_p
->grpcont
) {
256 /* if wrong way stem, account for it as best we can */
257 if (gs_p
->stemdir
== UP
) {
258 edge
+= (stemroom(gs_p
) - 1.0) * STEPSIZE
;
273 * Look at every GRPSYL in voice 3, if any. If it is "standing in" for
274 * the normal voice, move result up if need be.
276 for ( ; altgs_p
!= 0; altgs_p
= altgs_p
->next
) {
277 if (altgs_p
->pvno
== normvoice
) {
278 switch (altgs_p
->grpcont
) {
280 if (altgs_p
->c
[RN
] > result
)
281 result
= altgs_p
->c
[RN
];
292 return (nearestline(result
));
298 * Abstract: Find lowest relative y coord of a group in one GRPSYL list.
302 * Description: This function goes down one of the linked lists of GRPSYLs,
303 * one that is for groups, not syllables, and finds the lowest
304 * relative y coordinate of any group containing notes. If there
305 * are no notes but there are rests, it returns 0. If there are
306 * only spaces, it returns 100. The answer, though, is rounded
307 * off to the nearest staff line. Besides the primary linked list
308 * of GRPSYLs, it also looks for GRPSYLs in the alternate list
309 * (voice 3 if it exists) and considers ones that are "standing in"
310 * for the first list's voice.
314 lowcoord(gs_p
, altgs_p
)
316 register struct GRPSYL
*gs_p
; /* starts pointing at first GRPSYL in list */
317 register struct GRPSYL
*altgs_p
;/* first GRPSYL of voice 3, if any */
321 int normvoice
; /* main voice we are dealing with, 1 or 2 */
322 float edge
; /* of a group in the other voice */
325 debug(32, "lowcoord file=%s line=%d", gs_p
->inputfile
,
327 result
= 100; /* init as if only spaces */
328 normvoice
= gs_p
->vno
; /* remember the voice we're dealing with */
331 * Loop through all groups (even grace), moving result down when
332 * something lower is found. Rests count as 0 (the middle line).
334 for ( ; gs_p
!= 0; gs_p
= gs_p
->next
) {
335 switch (gs_p
->grpcont
) {
338 /* if wrong way stem, account for it as best we can */
339 if (gs_p
->stemdir
== DOWN
) {
340 edge
-= (stemroom(gs_p
) - 1.0) * STEPSIZE
;
355 * Look at every GRPSYL in voice 3, if any. If it is "standing in" for
356 * the normal voice, move result up if need be.
358 for ( ; altgs_p
!= 0; altgs_p
= altgs_p
->next
) {
359 if (altgs_p
->pvno
== normvoice
) {
360 switch (altgs_p
->grpcont
) {
362 if (altgs_p
->c
[RS
] < result
)
363 result
= altgs_p
->c
[RS
];
374 return (nearestline(result
));
380 * Abstract: Sets relative coordinates for rests in one CHORD/STAFF.
384 * Description: This function is given the top GRPSYL on a STAFF in a CHORD.
385 * It sets the relative coordinates of each rest GRPSYL on this
390 procrests(ch_p
, staff_p
, gs1_p
, limhigh
, limlow
)
392 struct CHORD
*ch_p
; /* the chord we are in */
393 struct STAFF
*staff_p
; /* the staff we are processing */
394 struct GRPSYL
*gs1_p
; /* point at top GRPSYL in chord */
395 double limhigh
; /* highest relative y coord below v1 */
396 double limlow
; /* lowest relative y coord above v2 */
399 RATIONAL endtime
; /* time at the end of the rest */
400 struct GRPSYL
*g_p
[MAXVOICES
+ 1]; /* index by vno, point at GRPSYL */
401 struct GRPSYL
*gs_p
; /* a GRPSYL we are now working on */
402 struct GRPSYL
*ogs_p
; /* other voice to be considered */
403 float wid
, asc
, des
; /* width, ascent, and descent of a rest */
404 int vscheme
; /* voice scheme */
405 int restsabove
; /* are these rests above another voice? */
406 int stafflines
; /* no. of lines in staff */
407 int v
; /* voice number */
408 float y
; /* relative y coord for this rest */
411 debug(32, "procrests file=%s line=%d limhigh=%f limlow=%f",
412 gs1_p
->inputfile
, gs1_p
->inputlineno
,
413 (float)limhigh
, (float)limlow
);
416 /* get voice scheme and number of lines in staff */
417 vscheme
= svpath(gs1_p
->staffno
, VSCHEME
)->vscheme
;
418 stafflines
= svpath(gs1_p
->staffno
, STAFFLINES
)->stafflines
;
420 /* set pointers to all nonspace groups in this chord on this staff */
421 for (v
= 1; v
<= MAXVOICES
; v
++) {
424 for (gs_p
= gs1_p
; gs_p
!= 0 && gs_p
->staffno
== gs1_p
->staffno
&&
425 gs_p
->grpsyl
== GS_GROUP
; gs_p
= gs_p
->gs_p
) {
426 if (gs_p
->grpcont
!= GC_SPACE
) {
427 g_p
[gs_p
->vno
] = gs_p
;
431 y
= 0.0; /* to avoid useless 'used before set' warning */
432 ogs_p
= 0; /* to avoid useless 'used before set' warning */
435 * Loop through each possible voice, setting its coords if it is a rest.
437 for (v
= 1; v
<= MAXVOICES
; v
++) {
441 if (gs_p
== 0 || gs_p
->grpcont
!= GC_REST
) {
445 /* find the time at the end of the rest */
446 endtime
= radd(ch_p
->starttime
, gs_p
->fulltime
);
448 /* find width, ascent, and descent of the rest */
449 restsize(gs_p
, &wid
, &asc
, &des
);
452 * Find out if another voice needs to be considered in the
453 * placement of this rest, and set ogs_p to that voice's first
457 if (vscheme
== V_2FREESTEM
||
458 vscheme
== V_3FREESTEM
&& gs_p
->pvno
!= 3) {
459 ogs_p
= gs_p
->pvno
== 1 ? staff_p
->groups_p
[1] :
460 staff_p
->groups_p
[0];
464 * Find the RY of the rest.
466 if (vscheme
== V_1
|| (vscheme
== V_2FREESTEM
||
467 vscheme
== V_3FREESTEM
) &&
468 hasspace(ogs_p
, ch_p
->starttime
, endtime
)) {
470 * There is either only 1 voice, or we are 2f/3f and the
471 * other voice is all spaces during this time. Usually
472 * RY should be 0. But for one-line staffs, whole
473 * rest characters need to be lowered so that they hang
476 if (stafflines
== 1 && gs_p
->basictime
== 1) {
483 * We are 2o, or 2f/3f with notes/rests in the other
484 * voice that we must avoid hitting. Set up the
485 * relative y coord, based on whether gs_p is acting
486 * as v1 or v2. We also have to set up restsabove
489 restsabove
= NO
; /* default value for now */
490 switch (gs_p
->pvno
) {
492 y
= limhigh
< -4 * STEPSIZE ?
493 0 : limhigh
+ 4 * STEPSIZE
;
494 restsabove
= ! hasspace(staff_p
->groups_p
[1],
496 /* also check for v3 groups acting as v2 */
497 for (ogs_p
= staff_p
->groups_p
[2];
498 ogs_p
!= 0 && restsabove
== NO
;
499 ogs_p
= ogs_p
->next
) {
500 if (ogs_p
->pvno
== 2 &&
501 ogs_p
->grpcont
!= GC_SPACE
) {
508 y
= limlow
> 4 * STEPSIZE ?
509 0 : limlow
- 4 * STEPSIZE
;
514 * Usually RY should be the y was set above. But
515 * if this is the upper voice, half rests and longer
516 * should be lower to fall within the staff when
517 * feasible, since they don't take much space
518 * vertically and we don't want needless ledger lines.
519 * (But nothing should ever be lowered if already on
520 * the center line.) Short rests need to be moved
521 * away from the other voice by varying amounts,
522 * depending on how tall they are. Quad whole rests
523 * below need to be raised a notch.
525 if (restsabove
== YES
) {
526 /* lower whole & double only if above middle */
527 if (gs_p
->basictime
<= 2 && y
> 0)
529 if (gs_p
->basictime
>= 16)
531 if (gs_p
->basictime
== 256)
534 if (gs_p
->basictime
>= 128)
536 if (gs_p
->basictime
== -1)
542 * If restdist was set by the user, use that instead of
543 * whatever we calculated above.
545 if (gs_p
->restdist
!= NORESTDIST
) {
546 y
= gs_p
->restdist
* STEPSIZE
;
549 /* set all the relative coords */
551 gs_p
->c
[RE
] = wid
/ 2;
552 gs_p
->c
[RW
] = -wid
/ 2 - gs_p
->padding
-
553 vvpath(gs_p
->staffno
, gs_p
->vno
, PAD
)->pad
;
555 gs_p
->c
[RN
] = y
+ asc
;
556 gs_p
->c
[RS
] = y
- des
;
558 /* if there are dot(s), add their widths to the east side */
559 if (gs_p
->dots
> 0) {
560 gs_p
->c
[RE
] += gs_p
->dots
* (width(FONT_MUSIC
,
561 DFLT_SIZE
, C_DOT
) + 2 * STDPAD
);
569 * Abstract: Sets relative coordinates for spaces in one GRPSYL list.
573 * Description: This function goes down one of the linked lists of GRPSYLs,
574 * one that is for groups, not syllables, and sets the relative
575 * coordinates for each space found. Usually these coords will
576 * be left as 0, the way they were calloc'ed, but not when there
577 * is padding or uncompressible spaces.
583 register struct GRPSYL
*gs_p
; /* starts pointing at first GRPSYL in list */
586 static float half_us_width
; /* half width of uncompressible space*/
587 char headchar
; /* char representing a note head */
588 int headfont
; /* music font for head char */
592 * Loop, setting all relative coords of spaces, except that if they are
593 * to be zero there's no need to set them, since calloc zeroed them.
594 * The vertical ones are always zero, and so is RX.
596 for ( ; gs_p
!= 0; gs_p
= gs_p
->next
) {
597 if (gs_p
->grpcont
!= GC_SPACE
)
600 if (gs_p
->uncompressible
== YES
) {
602 * If this is the first time in here, set this to half
603 * a blank quarter note head plus standard pad.
605 if (half_us_width
== 0.0) {
606 headchar
= nheadchar(get_shape_num("blank"),
608 half_us_width
= width(headfont
, DFLT_SIZE
,
609 headchar
) / 2.0 + STDPAD
;
612 /* center the imaginary note head */
613 gs_p
->c
[RE
] = half_us_width
/ 2;
614 gs_p
->c
[RW
] = -half_us_width
/ 2;
616 /* apply global user requested padding; notice that
617 * normal spaces (s) don't get this */
618 gs_p
->c
[RW
] -= vvpath(gs_p
->staffno
,
619 gs_p
->vno
, PAD
)->pad
;
622 /* add any user requested padding */
623 gs_p
->c
[RW
] -= gs_p
->padding
;
628 * Name: finalgroupproc()
630 * Abstract: Do final processing of groups.
632 * Returns: pointer to the first GRPSYL after these groups, 0 if none
634 * Description: This function is given the GRPSYL for the first (topmost) voice
635 * that is on this staff in this chord. It find what other
636 * GRPSYLs exist. For all the nonspace groups, it applies any
637 * horizontal offsets needed.
640 static struct GRPSYL
*
641 finalgroupproc(gs1_p
)
643 struct GRPSYL
*gs1_p
; /* first voice on this staff in this chord */
646 struct GRPSYL
*g_p
[MAXVOICES
]; /* point at nonspace voices' groups */
647 struct GRPSYL
*gs_p
; /* point at groups in the chord */
648 struct GRPSYL
*last_p
; /* point at last nonspace group */
649 int numgrps
; /* how many nonspace groups are here */
650 int staffno
; /* staff these groups are on */
651 int n
; /* loop variable */
652 float offset
; /* of each when + and - are used */
653 float edge
; /* west or east coord of group 1 or 2 */
654 int pack
; /* optimization for voice 3 */
657 staffno
= gs1_p
->staffno
; /* remember staffno of first group */
658 numgrps
= 0; /* no groups found yet */
659 last_p
= 0; /* no last nonspace group yet */
661 /* find all groups in this chord on this staff; remember nonspaces */
662 for (gs_p
= gs1_p
; gs_p
!= 0 && gs_p
->staffno
== staffno
&&
663 gs_p
->grpsyl
== GS_GROUP
; gs_p
= gs_p
->gs_p
) {
664 if (gs_p
->grpcont
!= GC_SPACE
) {
665 g_p
[numgrps
++] = gs_p
;
671 * If all groups on this staff were spaces, just make sure clef is
672 * marked correctly and return, though it's unlikely we have a clef
673 * change before a space.
680 /* nothing to do for tab, since "ho" is ignored and rests invisible */
681 if (is_tab_staff(g_p
[0]->staffno
))
684 /* for any voice with a user supplied offset value, apply it now */
685 for (n
= 0; n
< numgrps
; n
++) {
686 if (g_p
[n
]->ho_usage
== HO_VALUE
)
687 shiftgs(g_p
[n
], g_p
[n
]->ho_value
* STEPSIZE
);
691 * If both voices 1 and 2 are nonspace, handle any ho "+" or "-".
693 if (numgrps
>= 2 && g_p
[0]->vno
== 1 && g_p
[1]->vno
== 2) {
695 * Verify and fix offsets. We did this in setgrps.c for note
696 * groups so that compatible note groups could then be handled
697 * together. But we need to check again in case rest groups
703 * Check each of these 2 groups: If it has "+" or "-" and the
704 * other one doesn't, shift it to be next to the other one on
705 * the appropriate side.
707 for (n
= 0; n
< 2; n
++) {
708 if ((g_p
[n
]->ho_usage
== HO_LEFT
||
709 g_p
[n
]->ho_usage
== HO_RIGHT
) &&
710 ! (g_p
[1-n
]->ho_usage
== HO_LEFT
||
711 g_p
[1-n
]->ho_usage
== HO_RIGHT
)) {
713 if (g_p
[n
]->ho_usage
== HO_LEFT
) {
715 g_p
[1-n
]->c
[RW
] - g_p
[n
]->c
[RE
]);
718 g_p
[1-n
]->c
[RE
] - g_p
[n
]->c
[RW
]);
724 * If one has "+" and one has "-", shift them each by half of
725 * the amount of space needed to avoid a collision.
727 if (g_p
[0]->ho_usage
== HO_LEFT
&&
728 g_p
[1]->ho_usage
== HO_RIGHT
) {
730 offset
= (g_p
[0]->c
[RE
] - g_p
[1]->c
[RW
]) / 2.0;
731 shiftgs(g_p
[0], -offset
);
732 shiftgs(g_p
[1], offset
);
734 if (g_p
[0]->ho_usage
== HO_RIGHT
&&
735 g_p
[1]->ho_usage
== HO_LEFT
) {
737 offset
= (g_p
[1]->c
[RE
] - g_p
[0]->c
[RW
]) / 2.0;
738 shiftgs(g_p
[0], offset
);
739 shiftgs(g_p
[1], -offset
);
742 } else if (g_p
[0]->vno
!= 3) {
744 * If only one of groups 1 and 2 is nonspace, check whether it
745 * has "+" or "-", and warn if so.
747 if (g_p
[0]->ho_usage
== HO_LEFT
|| g_p
[0]->ho_usage
== HO_RIGHT
)
750 g_p
[0]->inputfile
, g_p
[0]->inputlineno
,
751 "voice %d cannot have horizontal offset '%c' since voice %d is not present; ignoring it",
753 g_p
[0]->ho_usage
== HO_LEFT ?
'-' :'+',
756 g_p
[0]->ho_usage
= HO_NONE
;
761 * If voice 3 and at least one other voice exist here, and the user
762 * didn't state an offset value for voice 3, offset it next to the
763 * other voices, on the left or right, as requested. But exclude the
764 * case where voice 3 was being treated as 1 or 2, by checking pvno
767 if (numgrps
> 1 && last_p
->pvno
== 3 && last_p
->ho_usage
!= HO_VALUE
) {
769 * See if we can pack v3 tightly against v1 and v2. (This will
770 * not be allowed if ho_usage != HO_NONE for any voice, or any
771 * other of many conditions doesn't hold true.)
773 pack
= v3pack(g_p
, numgrps
);
774 if (pack
!= PK_NONE
) {
776 * Yes, we can; shift v3 a little if necessary. Make
777 * it so that v3's stem is one stepsize away from the
778 * group that its stem is pointing toward.
782 /* since v3 is on left, v2 must exist, and is
783 * the voice preceding v3 in g_p */
784 shiftgs(last_p
, -STEPSIZE
+
785 widest_head(last_p
) / 2.0 +
786 g_p
[numgrps
-2]->c
[RW
]);
789 /* since v3 is on right, v1 must exist, and is
790 * the first voice in g_p */
791 shiftgs(last_p
, STEPSIZE
+
793 widest_head(last_p
) / 2.0);
795 /* for PK_CENTER, nothing to do */
798 } else if (last_p
->ho_usage
== HO_LEFT
) {
800 /* find leftmost edge of the other voice(s) */
801 edge
= g_p
[0]->c
[RW
];
802 for (n
= 1; n
< numgrps
- 1; n
++) {
803 if (g_p
[n
]->c
[RW
] < edge
)
804 edge
= g_p
[n
]->c
[RW
];
806 /* set right edge of voice 3 == left edge of others */
807 shiftgs(last_p
, edge
- last_p
->c
[RE
]);
809 } else { /* HO_RIGHT, or HO_NONE which defaults to HO_RIGHT */
811 /* find rightmost edge of the other voice(s) */
812 edge
= g_p
[0]->c
[RE
];
813 for (n
= 1; n
< numgrps
- 1; n
++) {
814 if (g_p
[n
]->c
[RE
] > edge
)
815 edge
= g_p
[n
]->c
[RE
];
817 /* set left edge of voice 3 == right edge of others */
818 shiftgs(last_p
, edge
- last_p
->c
[RW
]);
820 } else if (g_p
[0]->vno
== 3 && (g_p
[0]->ho_usage
== HO_LEFT
||
821 g_p
[0]->ho_usage
== HO_RIGHT
)) {
823 * If the first (and thus only) voice is 3, it should not have
827 g_p
[0]->inputfile
, g_p
[0]->inputlineno
,
828 "voice 3 cannot have horizontal offset '%c' since voices 1 and 2 are not present; ignoring it",
829 g_p
[0]->ho_usage
== HO_LEFT ?
'-' :'+');
831 g_p
[0]->ho_usage
= HO_NONE
;
834 /* in case of midmeasure clef change, make sure it's marked right */
837 /* return the first GRPSYL after the groups we processed */
844 * Abstract: Decide whether v3 can be packed tighter than the default.
846 * Returns: PK_NONE no, it can't
847 * PK_LEFT pack tightly on left
848 * PK_RIGHT pack tightly on right
849 * PK_CENTER pack in the center
851 * Description: This function decides whether the voice 3 group can be packed
852 * in more tightly against voices 1 and 2 than the usual default
853 * of just putting v3's group's rectangle to the right of the
854 * other voices. If there seems to be any danger that v3 would
855 * collide with v1 or v2, it gives up and returns PK_NONE. It
856 * could be made a lot more sophisticated and not give up so soon
857 * in many cases. However many of these improvements can't be
858 * done very well at this stage of the game, where we don't know
859 * yet about stem lengths, beam positions, etc.
865 struct GRPSYL
*g_p
[]; /* point at nonspace voices' groups */
866 int numgrps
; /* how many nonspace groups are here */
869 struct GRPSYL
*gs_p
; /* point at a group */
870 struct GRPSYL
*v3_p
; /* point at v3's group */
871 struct NOTE
*v3note_p
; /* v3 note that neighbors other voice*/
872 struct NOTE
*onote_p
; /* v1/v2 note that neighbors v3 */
873 float north
; /* highest coord of note or acc */
874 float south
; /* lowest coord of note or acc */
875 float topdesc
; /* descent of acc of top group */
876 float botasc
; /* ascent of acc of bottom group */
877 int v3hasacc
, otherhasacc
; /* do v3 and other voice have acc(s)?*/
879 int n
; /* loop variable */
880 int k
; /* loop variable */
883 /* either v1 or v2 must be nonspace */
888 /* point at v3's group for convenience */
889 v3_p
= g_p
[numgrps
- 1];
891 /* set up what the answer will be if we can apply the optimization */
892 if (v3_p
->basictime
>= 2) {
893 /* there is a stem, so offset such that stem will avoid v1/v2 */
894 if (v3_p
->stemdir
== UP
) {
900 pack
= PK_CENTER
; /* no stem, so we can center v3 */
903 /* v3 must not be standing in for v1 or v2 */
904 if (v3_p
->pvno
!= 3) {
908 /* if v3 would be on left, it must not have a flag or be start of beam*/
909 if (pack
== PK_LEFT
&& (v3_p
->basictime
>= 8 && v3_p
->beamloc
== NOITEM
910 || v3_p
->beamloc
== STARTITEM
)) {
914 /* if v3 would be on right, it must not have grace groups preceding */
915 if (pack
== PK_RIGHT
&& v3_p
->prev
!= 0 &&
916 v3_p
->prev
->grpvalue
== GV_ZERO
) {
920 /* v3 cannot have slashes or alternation */
921 if (v3_p
->slash_alt
!= 0) {
926 * Loop through all voices, checking for rule violations. We do it
927 * in reverse so that we know v3 is notes (the first check) before
928 * checking the other voices.
930 for (n
= numgrps
- 1; n
>= 0; n
--) {
931 gs_p
= g_p
[n
]; /* set to current voice for convenience */
933 /* voice must be notes, and not measure repeat */
934 if (gs_p
->grpcont
!= GC_NOTES
|| gs_p
->is_meas
) {
938 /* voice cannot have user requested horizontal offset */
939 if (gs_p
->ho_usage
!= HO_NONE
) {
943 /* voice cannot have a "with" list */
944 if (gs_p
->nwith
!= 0) {
948 /* voice cannot have a roll */
949 if (gs_p
->roll
!= NOITEM
) {
953 /* do voice specific checks */
957 /* stem must be up */
958 if (gs_p
->stemdir
!= UP
) {
962 /* find neighboring notes of v1 and v3 */
963 v3note_p
= &v3_p
->notelist
[0];
964 onote_p
= &gs_p
->notelist
[gs_p
->nnotes
- 1];
966 /* neighboring notes in v1 & v3 must not be too close */
967 if (onote_p
->stepsup
< v3note_p
->stepsup
+ 2 ||
968 onote_p
->stepsup
== v3note_p
->stepsup
+ 2 &&
970 (v3_p
->basictime
< 1 || gs_p
->basictime
< 1)) {
974 /* if 2 steps apart and on lines and v3 would not be on
975 * right, v1 can't have dots and v3 can't unless it
977 if (onote_p
->stepsup
== v3note_p
->stepsup
+ 2 &&
978 EVEN(v3note_p
->stepsup
) &&
980 pack
!= PK_RIGHT
&& v3_p
->dots
!= 0)) {
985 * Find the lowest extension of any accidental in v1.
986 * If no accidentals, the initial value for "south"
987 * will remain. It's not good enough to check accs
988 * only on the neighboring notes, because some of them
989 * stick out pretty far. We have to go through these
990 * gyrations because group boundaries do not consider
991 * accidentals that stick out up or down.
994 south
= onote_p
->c
[RY
] - STEPSIZE
+ 0.001;
995 for (k
= 0; k
< gs_p
->nnotes
; k
++) {
996 accdimen(&gs_p
->notelist
[k
], (float *)0,
997 &topdesc
, (float *)0);
998 if (gs_p
->notelist
[k
].c
[RY
] - topdesc
< south
) {
999 south
= gs_p
->notelist
[k
].c
[RY
]
1002 if (gs_p
->notelist
[k
].accidental
!= '\0') {
1006 /* similarly, find highest extension of v3 accs */
1008 north
= v3note_p
->c
[RY
] + STEPSIZE
- 0.001;
1009 for (k
= 0; k
< v3_p
->nnotes
; k
++) {
1010 accdimen(&v3_p
->notelist
[k
], &botasc
,
1011 (float *)0, (float *)0);
1012 if (v3_p
->notelist
[k
].c
[RY
] + botasc
> north
) {
1013 north
= v3_p
->notelist
[k
].c
[RY
]
1016 if (v3_p
->notelist
[k
].accidental
!= '\0') {
1020 /* if v1 and v3 overlap due to acc(s), fail */
1021 if (south
< north
) {
1024 if (v3hasacc
== YES
) {
1029 if (v3hasacc
== YES
&&
1030 otherhasacc
== YES
) {
1035 if (otherhasacc
== YES
) {
1042 /* if left or right offset, neighboring notes in v1 &
1043 * v3 must not have parentheses when accs exist */
1044 if ((pack
!= PK_CENTER
|| v3hasacc
== YES
|| otherhasacc
== YES
) &&
1045 (v3note_p
->note_has_paren
|| onote_p
->note_has_paren
)) {
1052 if (gs_p
->stemdir
!= DOWN
) {
1056 /* find neighboring notes of v2 and v3 */
1057 v3note_p
= &v3_p
->notelist
[v3_p
->nnotes
- 1];
1058 onote_p
= &gs_p
->notelist
[0];
1060 /* neighboring notes in v1 & v3 must not be too close */
1061 if (onote_p
->stepsup
> v3note_p
->stepsup
- 2 ||
1062 onote_p
->stepsup
== v3note_p
->stepsup
- 2 &&
1063 pack
!= PK_CENTER
&&
1064 (v3_p
->basictime
< 1 || gs_p
->basictime
< 1)) {
1068 /* if 2 steps apart and on lines and v3 would not be on
1069 * right, neither can have dots */
1070 if (onote_p
->stepsup
== v3note_p
->stepsup
- 2 &&
1071 EVEN(v3note_p
->stepsup
) &&
1073 (gs_p
->dots
!= 0 || v3_p
->dots
!= 0)) {
1078 * Find the highest extension of any accidental in v2.
1079 * If no accidentals, the initial value for "north"
1083 north
= onote_p
->c
[RY
] + STEPSIZE
- 0.001;
1084 for (k
= 0; k
< gs_p
->nnotes
; k
++) {
1085 accdimen(&gs_p
->notelist
[k
], &botasc
,
1086 (float *)0, (float *)0);
1087 if (gs_p
->notelist
[k
].c
[RY
] + botasc
> north
) {
1088 north
= gs_p
->notelist
[k
].c
[RY
]
1091 if (gs_p
->notelist
[k
].accidental
!= '\0') {
1095 /* similarly, find highest extension of v3 accs */
1097 south
= v3note_p
->c
[RY
] - STEPSIZE
+ 0.001;
1098 for (k
= 0; k
< v3_p
->nnotes
; k
++) {
1099 accdimen(&v3_p
->notelist
[k
], (float *)0,
1100 &topdesc
, (float *)0);
1101 if (v3_p
->notelist
[k
].c
[RY
] - topdesc
< south
) {
1102 south
= v3_p
->notelist
[k
].c
[RY
]
1105 if (v3_p
->notelist
[k
].accidental
!= '\0') {
1109 /* if v2 and v3 overlap due to acc(s), fail */
1110 if (south
< north
) {
1113 if (v3hasacc
== YES
) {
1118 if (v3hasacc
== YES
&&
1119 otherhasacc
== YES
) {
1122 if (v3hasacc
== YES
&&
1123 gs_p
->nnotes
>= 2 &&
1125 gs_p
->notelist
[1].stepsup
+ 1) {
1130 if (otherhasacc
== YES
) {
1137 /* if left or right offset, neighboring notes in v2 &
1138 * v3 must not have parentheses when accs exist */
1139 if ((pack
!= PK_CENTER
|| v3hasacc
== YES
|| otherhasacc
== YES
) &&
1140 (v3note_p
->note_has_paren
|| onote_p
->note_has_paren
)) {
1148 /* all checks passed, so return the answer */
1155 * Abstract: If midmeasure clef change at this chord, mark in right GRPSYL.
1159 * Description: This function is given the GRPSYL for the first (topmost) voice
1160 * that is on this staff in this chord. If the clef changed at
1161 * this time value, locllnotes() in setnotes.c will have set the
1162 * "clef" field in each of the GRPSYLs in this chord on this
1163 * staff (actually in their first preceding grace group, if
1164 * any). But it should only be set in the GRPSYL that has the
1165 * westernmost west boundary. So this function erases it from
1166 * any other GRPSYLs.
1172 struct GRPSYL
*gs1_p
; /* starts at first voice on this staff */
1175 struct GRPSYL
*g_p
[MAXVOICES
]; /* point at voices' groups */
1176 struct GRPSYL
*gs_p
; /* point at groups in the chord */
1177 int numgrps
; /* how many groups are in the chord */
1178 struct GRPSYL
*westgs_p
; /* remember westernmost */
1179 int staffno
; /* staff number */
1180 int n
; /* loop variable */
1183 staffno
= gs1_p
->staffno
; /* remember staffno of first group */
1185 /* point at all groups in this chord on this staff */
1186 numgrps
= 0; /* no groups found yet */
1187 for (gs_p
= gs1_p
; gs_p
!= 0 && gs_p
->staffno
== staffno
&&
1188 gs_p
->grpsyl
== GS_GROUP
; gs_p
= gs_p
->gs_p
) {
1189 g_p
[numgrps
++] = gs_p
;
1193 * For each that is preceded by grace group(s), change the pointer to
1194 * point at the first in that sequence of grace groups. Any clef
1195 * change would occur at that group.
1197 for (n
= 0; n
< numgrps
; n
++) {
1198 while (g_p
[n
]->prev
!= 0 && g_p
[n
]->prev
->grpvalue
== GV_ZERO
) {
1199 g_p
[n
] = g_p
[n
]->prev
;
1203 /* if clef not marked in first, it's not marked in any, so return */
1204 if (g_p
[0]->clef
== NOCLEF
) {
1208 westgs_p
= 0; /* prevent useless "used before set" warning */
1211 * Find the westernmost group of notes, if any; if it's a tie, use the
1212 * first one. We don't want to put clefs in front of rests, spaces, or
1213 * mrpt, unless we have no choice.
1215 for (n
= 0; n
< numgrps
; n
++) {
1216 if (g_p
[n
]->grpcont
== GC_NOTES
&& g_p
[n
]->is_meas
== NO
) {
1217 if (westgs_p
== 0 || g_p
[n
]->c
[RW
] < westgs_p
->c
[RW
]) {
1222 /* we have no choice; arbitrarily choose the first voice */
1223 if (westgs_p
== NULL
) {
1227 /* erase clef from all but the group found above */
1228 for (n
= 0; n
< numgrps
; n
++) {
1229 if (g_p
[n
] != westgs_p
) {
1230 g_p
[n
]->clef
= NOCLEF
;
1234 /* if there were no notes, there will be no clef here */
1235 if (westgs_p
== 0) {
1239 /* move western boundary of GRPSYL to allow room to print the clef */
1240 westgs_p
->c
[RW
] -= clefwidth(westgs_p
->clef
, YES
) + CLEFPAD
;
1243 * If this is a grace group, we also have to alter its main group's
1244 * boundary, because the main group's boundary needs to enclose all
1247 for (gs_p
= westgs_p
; gs_p
->grpvalue
== GV_ZERO
; gs_p
= gs_p
->next
) {
1250 if (gs_p
!= westgs_p
) {
1251 gs_p
->c
[RW
] -= clefwidth(westgs_p
->clef
, YES
) + CLEFPAD
;
1258 * Abstract: Find the size of a rest.
1262 * Description: This function is given a GRPSYL which is a rest. It returns
1263 * the width, ascent, and descent through pointers.
1267 restsize(gs_p
, wid_p
, asc_p
, des_p
)
1269 register struct GRPSYL
*gs_p
; /* the GRPSYL containing the rest */
1270 float *wid_p
, *asc_p
, *des_p
; /* return width, ascent, and descent of rest */
1273 char rchar
; /* char for the rest */
1274 int size
; /* font size */
1277 /* multirest has no music character; just return the answer */
1278 if (gs_p
->basictime
< -1) {
1279 *wid_p
= MINMULTIWIDTH
;
1280 *asc_p
= 2 * STEPSIZE
;
1281 *des_p
= 2 * STEPSIZE
;
1285 /* on a tab staff rests are invisible, so set to a very small size */
1286 if (is_tab_staff(gs_p
->staffno
)) {
1287 *wid_p
= *asc_p
= *des_p
= 0.01;
1292 * The "normal" rest case. Find the name of the character. Then get
1293 * the width, ascent, and descent of the rest.
1295 rchar
= restchar(gs_p
->basictime
);
1296 size
= (gs_p
->grpsize
== GS_NORMAL ? DFLT_SIZE
: SMALLSIZE
);
1297 *wid_p
= width(FONT_MUSIC
, size
, rchar
);
1298 *asc_p
= ascent(FONT_MUSIC
, size
, rchar
);
1299 *des_p
= descent(FONT_MUSIC
, size
, rchar
);
1305 * Abstract: Sets relative horizontal coords for syllables in 1 GRPSYL list.
1309 * Description: This function goes down one of the linked lists of GRPSYLs,
1310 * one that is for syllables, not groups, and sets the relative
1311 * horizontal coordinates for each syllable found.
1317 register struct GRPSYL
*gs_p
; /* starts pointing at first GRPSYL in list */
1320 float wid_b4_syl
; /* width of leading non-lyrics */
1321 float wid_real_syl
; /* width of actual lyric */
1322 float wid_after_syl
; /* width of trailing non-lyrics */
1323 float lyricsalign
; /* fraction of syl to go left of chord center*/
1324 int font
, size
; /* of the last char in a syllable */
1325 char lc
; /* last char of syllable */
1328 debug(32, "procsyls file=%s line=%d", gs_p
->inputfile
,
1330 /* find what fraction of each syl should go left of center of chord */
1331 lyricsalign
= svpath(gs_p
->staffno
, LYRICSALIGN
)->lyricsalign
;
1334 * Set coords for every syllable. A syllable can consist of 3 parts.
1335 * The middle part is the actual lyric. The optional first and last
1336 * parts are surrounded in the user's input by angle brackets. The
1337 * syllable is to be positioned such that "lyricsalign" of the middle
1338 * part goes to the left of the chord's center, and the rest goes to
1339 * the right; unless sylposition is set, in which case the left edge of
1340 * the actual lyric is offset by that many points from the chord's
1341 * center. Then adjust the east side for padding purposes.
1343 for ( ; gs_p
!= 0; gs_p
= gs_p
->next
) {
1344 sylwidth(gs_p
->syl
, &wid_b4_syl
, &wid_real_syl
, &wid_after_syl
);
1347 if (gs_p
->sylposition
== NOSYLPOSITION
) {
1348 gs_p
->c
[RW
] = -lyricsalign
* wid_real_syl
- wid_b4_syl
;
1349 gs_p
->c
[RE
] = (1 - lyricsalign
) * wid_real_syl
+
1352 gs_p
->c
[RW
] = gs_p
->sylposition
* POINT
- wid_b4_syl
;
1353 gs_p
->c
[RE
] = gs_p
->sylposition
* POINT
+ wid_real_syl
+
1357 /* get last char of syl; if null syl don't alter RE any more */
1358 lc
= last_char(gs_p
->syl
);
1363 * If this is not the last syllable of the measure, and it
1364 * doesn't end in '-', leave space for a blank after it, to
1365 * separate it from the next syllable.
1367 if ( gs_p
->next
!= 0 && lc
!= '-') {
1368 end_fontsize(gs_p
->syl
, &font
, &size
);
1369 gs_p
->c
[RE
] += width(font
, size
, ' ');
1373 * If this is the last syllable of the measure, and it ends in
1374 * '-', back up a space, letting the '-' go into the bar line.
1376 if ( gs_p
->next
== 0 && lc
== '-' ) {
1377 end_fontsize(gs_p
->syl
, &font
, &size
);
1378 gs_p
->c
[RE
] -= width(font
, size
, ' ');
1384 * Name: apply_staffscale()
1386 * Abstract: Scale all relative coordinates according to staffscale.
1390 * Description: Throughout Mup, we are able to almost entirely avoid dealing
1391 * with the "scale" parameter, by the following trick: We pretend
1392 * the paper is a different size than it really is, by the inverse
1393 * of the "scale" factor, place and print everything at standard
1394 * size, and then at the end apply the scale to everything at
1395 * once, in PostScript. (Margins are exempt from scaling, hence
1396 * the EFF_* macros to cancel it out.)
1398 * But for the "staffscale" parameter, this kind of trick only
1399 * works up to a point. As long as we are dealing only with
1400 * relative coords on one staff at a time, as we have up to this
1401 * point in the program, we can ignore staffscale. But now we're
1402 * about to start dealing with chord coords, and chords span
1403 * staffs. So the jig is up.
1405 * This function goes through all the relative coords set so far,
1406 * and scales them according to staffscale. It also scales the
1407 * font sizes in strings. From this point on staffscale must
1408 * always be considered.
1415 struct MAINLL
*mainll_p
; /* point at items in main linked list*/
1416 struct STAFF
*staff_p
; /* point at a staff structure */
1417 register float staffscale
; /* current staffscale */
1418 register struct GRPSYL
*gs_p
; /* point at groups */
1419 register struct NOTE
*note_p
; /* point at notes */
1420 struct STUFF
*stuff_p
; /* point at a stuff structure */
1421 int n
; /* loop variable */
1422 int v
; /* voice number, 0 to 2 */
1425 debug(16, "apply_staffscale");
1430 * Loop down the main linked list looking for each staff.
1432 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
1434 switch (mainll_p
->str
) {
1436 /* apply SSVs to keep staffscale up to date */
1437 asgnssv(mainll_p
->u
.ssv_p
);
1441 staff_p
= mainll_p
->u
.staff_p
;
1442 break; /* break out to handle staffs */
1445 continue; /* nothing to do */
1448 /* get staffscale for this staff in this measure */
1449 staffscale
= svpath(staff_p
->staffno
, STAFFSCALE
)->staffscale
;
1451 /* go through each voice this staff has */
1452 for (v
= 0; v
< MAXVOICES
; v
++) {
1454 /* and each group in each voice */
1455 for (gs_p
= staff_p
->groups_p
[v
]; gs_p
!= 0;
1456 gs_p
= gs_p
->next
) {
1458 /* scale the group's relative coords */
1459 gs_p
->c
[RX
] *= staffscale
;
1460 gs_p
->c
[RN
] *= staffscale
;
1461 gs_p
->c
[RY
] *= staffscale
;
1462 gs_p
->c
[RS
] *= staffscale
;
1464 /* but don't disturb this E,W constant value */
1465 /* (see setgrps.c and abshorz.c) */
1466 if (gs_p
->c
[RE
] != TEMPMRPTWIDTH
/ 2.0) {
1467 gs_p
->c
[RE
] *= staffscale
;
1468 gs_p
->c
[RW
] *= staffscale
;
1471 gs_p
->xdotr
*= staffscale
;
1473 /* usually we're done caring about padding */
1474 /* by now, but not always, so scale it */
1475 gs_p
->padding
*= staffscale
;
1477 if (gs_p
->grpcont
== GC_NOTES
) {
1478 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1479 note_p
= &gs_p
->notelist
[n
];
1481 /* scale note's rel. coords */
1482 note_p
->c
[RW
] *= staffscale
;
1483 note_p
->c
[RX
] *= staffscale
;
1484 note_p
->c
[RE
] *= staffscale
;
1485 note_p
->c
[RN
] *= staffscale
;
1486 note_p
->c
[RY
] *= staffscale
;
1487 note_p
->c
[RS
] *= staffscale
;
1489 note_p
->waccr
*= staffscale
;
1490 note_p
->ydotr
*= staffscale
;
1491 note_p
->wlparen
*= staffscale
;
1492 note_p
->erparen
*= staffscale
;
1494 /* this isn't really scaling,
1495 * but it's a convenient place
1496 * to undo CSS_STEPS */
1497 if (gs_p
->stemto
== CS_ABOVE
&&
1498 n
<= gs_p
->stemto_idx
) {
1499 gs_p
->notelist
[n
].stepsup
-= CSS_STEPS
;
1500 gs_p
->notelist
[n
].ydotr
-=
1501 CSS_STEPS
* STEPSIZE
* staffscale
;
1502 } else if (gs_p
->stemto
== CS_BELOW
&&
1503 n
>= gs_p
->stemto_idx
) {
1504 gs_p
->notelist
[n
].stepsup
+= CSS_STEPS
;
1505 gs_p
->notelist
[n
].ydotr
+=
1506 CSS_STEPS
* STEPSIZE
* staffscale
;
1511 for (n
= 0; n
< gs_p
->nwith
; n
++) {
1512 (void)resize_string(gs_p
->withlist
[n
],
1520 /* scale the syllables' coords and font sizes */
1521 for (v
= 0; v
< staff_p
->nsyllists
; v
++) {
1522 for (gs_p
= staff_p
->syls_p
[v
]; gs_p
!= 0;
1523 gs_p
= gs_p
->next
) {
1524 gs_p
->c
[RW
] *= staffscale
;
1525 gs_p
->c
[RX
] *= staffscale
;
1526 gs_p
->c
[RE
] *= staffscale
;
1527 gs_p
->c
[RN
] *= staffscale
;
1528 gs_p
->c
[RY
] *= staffscale
;
1529 gs_p
->c
[RS
] *= staffscale
;
1531 (void)resize_string(gs_p
->syl
, staffscale
,
1532 gs_p
->inputfile
, gs_p
->inputlineno
);
1536 /* scale the STUFF structures' font sizes */
1537 /* (their coords won't be set until we get to stuff.c) */
1538 for (stuff_p
= staff_p
->stuff_p
; stuff_p
!= 0;
1539 stuff_p
= stuff_p
->next
) {
1540 if (stuff_p
->string
!= 0) {
1541 (void)resize_string(
1543 stuff_p
->all
== YES ? Score
.staffscale
1546 stuff_p
->inputlineno
);
1555 * Abstract: Set relative horizontal coordinates of each chord.
1559 * Description: This function goes through the chord lists, and for each chord,
1560 * sets its horizontal relative coordinates, by going down the
1561 * list of GRPSYLs hanging off it.
1568 struct CHORD
*ch_p
; /* point at a chord */
1569 struct CHORD
*pch_p
; /* point at previous chord */
1570 struct CHORD
*ppch_p
; /* point at chord before that */
1571 struct MAINLL
*mainll_p
; /* point at items in main linked list*/
1572 struct GRPSYL
*gs_p
; /* point at groups */
1573 struct GRPSYL
*nsyl_p
; /* point at next syl */
1574 struct GRPSYL
*psyl_p
; /* point at previous syl */
1575 float stealable
; /* from previous chord */
1576 float eff
; /* effective coord */
1579 debug(16, "relxchord");
1583 * Loop down the main linked list looking for each chord list headcell.
1585 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
1587 /* need to keep "pad" up to date */
1588 if (mainll_p
->str
== S_SSV
)
1589 asgnssv(mainll_p
->u
.ssv_p
);
1591 if (mainll_p
->str
!= S_CHHEAD
)
1592 continue; /* skip everything but chord HC */
1595 * Pretend that all the chords will be jammed tightly together,
1596 * starting at absolute coordinate zero. We set absolute
1597 * coords here for the benefit of effwest(), but they will be
1598 * overwritten with their true values later in abshorz().
1600 mainll_p
->u
.chhead_p
->ch_p
->c
[AW
] = 0.0; /* west of 1st chord*/
1603 * First, loop forwards through the chord list, setting the
1604 * boundaries and widths of each chord based only on its
1605 * groups. The chord is to extend outwards just enough to
1606 * contain every group.
1608 for (ch_p
= mainll_p
->u
.chhead_p
->ch_p
; ch_p
!= 0;
1609 ch_p
= ch_p
->ch_p
) {
1611 /* start chord as if 0 width */
1616 /* loop through groups, expanding chord when necessary*/
1617 for (gs_p
= ch_p
->gs_p
; gs_p
!= 0; gs_p
= gs_p
->gs_p
) {
1618 if (gs_p
->grpsyl
== GS_GROUP
) {
1620 * If last chord in measure, add pad
1621 * parameter on right side of groups;
1622 * but not for collapseable spaces (s).
1624 if (ch_p
->ch_p
== 0 &&
1625 (gs_p
->grpcont
!= GC_SPACE
||
1626 gs_p
->uncompressible
== YES
)) {
1627 gs_p
->c
[RE
] += vvpath(gs_p
->
1628 staffno
, gs_p
->vno
, PAD
)->pad
*
1629 svpath(gs_p
->staffno
,
1630 STAFFSCALE
)->staffscale
;
1633 eff
= effwest(mainll_p
, ch_p
, gs_p
);
1634 if (eff
< ch_p
->c
[RW
])
1636 eff
= effeast(ch_p
, gs_p
);
1637 if (eff
> ch_p
->c
[RE
])
1642 /* store width; will be updated later to include syls */
1643 ch_p
->width
= ch_p
->c
[RE
] - ch_p
->c
[RW
];
1645 /* set phony absolute coords for effwest() */
1646 ch_p
->c
[AX
] = ch_p
->c
[AW
] - ch_p
->c
[RW
];
1647 ch_p
->c
[AE
] = ch_p
->c
[AX
] + ch_p
->c
[RE
];
1648 if (ch_p
->ch_p
!= 0)
1649 ch_p
->ch_p
->c
[AW
] = ch_p
->c
[AE
];
1653 * Loop again through each chord in this list, this time
1654 * expanding chords when necessary to include eastward
1655 * extensions of syllables. Work right to left, so that when
1656 * a syllable steals space from the following chord, the
1657 * following chord has already been widened eastwards, if it
1658 * needed to be, based on its syllables.
1660 /* find last chord in the chord LL */
1661 ch_p
= mainll_p
->u
.chhead_p
->ch_p
; /* first chord */
1662 while (ch_p
->ch_p
!= 0)
1665 /* loop backwards through them (too bad there's no back ptr) */
1666 for ( ; ch_p
!= 0; ch_p
= prevchord(mainll_p
, ch_p
)) {
1668 * Loop through the linked list of GRPSYLs hanging off
1669 * this chord, altering RE when finding a syl that
1670 * sticks out farther. There is one exception to
1671 * this. If a syllable extends farther east than any
1672 * one so far, a test is made so that it can steal
1673 * space from the following chord if that chord has
1674 * no syllable there.
1676 for (gs_p
= ch_p
->gs_p
; gs_p
!= 0; gs_p
= gs_p
->gs_p
) {
1678 /* if not a syl or not sticking out east */
1679 if (gs_p
->grpsyl
!= GS_SYLLABLE
||
1680 gs_p
->c
[RE
] <= ch_p
->c
[RE
])
1683 /* syl seems to be sticking out east */
1686 * If this is the last chord in the measure,
1687 * the chord boundary must include the syl.
1689 if (ch_p
->ch_p
== 0) {
1690 ch_p
->c
[RE
] = gs_p
->c
[RE
];
1695 * The syl is sticking out east of the current
1696 * chord boundary, and this is not the last
1697 * chord in the measure. See if the next
1698 * chord contains the next syl of this verse.
1699 * If not, there's an empty space there, and
1700 * we can let the current syl steal space from
1703 nsyl_p
= nextchsyl(gs_p
, ch_p
);
1706 * Next chord has no syl here. We can
1707 * steal its space. If the syl is so
1708 * long that even that isn't enough
1709 * room, we'll force the current chord
1710 * boundary far enough out to contain
1713 if (gs_p
->c
[RE
] > ch_p
->c
[RE
] +
1714 ch_p
->ch_p
->width
) {
1715 ch_p
->c
[RE
] = gs_p
->c
[RE
] -
1720 * Next chord has a syl, so we can't
1721 * steal its space. Extend this chord.
1723 ch_p
->c
[RE
] = gs_p
->c
[RE
];
1727 /* revise width; will be revised again later */
1728 ch_p
->width
= ch_p
->c
[RE
] - ch_p
->c
[RW
];
1730 } /* end of backwards loop through chords in this measure */
1733 * Loop again through each chord in this list, this time
1734 * expanding chords when necessary to include westward
1735 * extensions of syllables. Work left to right, so that when
1736 * a syllable steals space from the preceding chord, the
1737 * preceding chord has already been widened westwards, if it
1738 * needed to be, based on its syllables.
1740 for (ch_p
= mainll_p
->u
.chhead_p
->ch_p
; ch_p
!= 0;
1741 ch_p
= ch_p
->ch_p
) {
1743 * Loop through the linked list of GRPSYLs hanging off
1744 * this chord, altering RW when finding a syl that
1745 * sticks out farther. There is one exception to
1746 * this. If a syllable extends farther west than any
1747 * one so far, a test is made so that it can steal
1748 * space from the following chord if that chord has
1749 * no syllable there.
1751 for (gs_p
= ch_p
->gs_p
; gs_p
!= 0; gs_p
= gs_p
->gs_p
) {
1753 /* if not a syl or not sticking out west */
1754 if (gs_p
->grpsyl
!= GS_SYLLABLE
||
1755 gs_p
->c
[RW
] >= ch_p
->c
[RW
])
1758 /* syl seems to be sticking out west */
1761 * If this is the first chord in the measure,
1762 * the chord boundary must include the syl.
1764 if (prevchord(mainll_p
, ch_p
) == 0) {
1765 ch_p
->c
[RW
] = gs_p
->c
[RW
];
1770 * The syl is sticking out west of the current
1771 * chord boundary, and this is not the first
1772 * chord in the measure. See if the previous
1773 * chord contains the previous syl of this
1774 * verse, or if the one before that stole
1775 * space from it. If not, there's an empty
1776 * space there, and we can let the current syl
1777 * steal space from the previous chord. Even
1778 * if the previous chord has no syl but the one
1779 * before stole some space from it, we can use
1780 * the part of the space it didn't steal.
1782 /* get prev chord, & prev syl in this verse */
1783 pch_p
= prevchord(mainll_p
, ch_p
);
1784 psyl_p
= prevchsyl(gs_p
, pch_p
);
1787 /* first, assume all of the previous */
1788 /* chord's width is available */
1789 stealable
= pch_p
->width
;
1792 * Get the chord before the previous.
1793 * If it exists and contains a syl,
1794 * syl may already be stealing space
1795 * east of it, in which case we can
1796 * only steal what's left over.
1798 ppch_p
= prevchord(mainll_p
, pch_p
);
1800 psyl_p
= prevchsyl(gs_p
,
1803 if (psyl_p
!= 0 && psyl_p
->c
[RE
]
1805 stealable
-= (psyl_p
->
1806 c
[RE
] - ppch_p
->c
[RE
]);
1811 * If our syl needs more space than is
1812 * available for stealing, widen our
1813 * chord by the necessary amount.
1815 if (gs_p
->c
[RW
] < ch_p
->c
[RW
] -
1817 ch_p
->c
[RW
] = gs_p
->c
[RW
] +
1821 * Prev chord has a syl, so we can't
1822 * steal its space. Extend this chord.
1824 ch_p
->c
[RW
] = gs_p
->c
[RW
];
1828 /* final revision of width */
1829 ch_p
->width
= ch_p
->c
[RE
] - ch_p
->c
[RW
];
1831 } /* end of forwards loop through chords in this measure */
1833 } /* end of loop through each CHHEAD in main linked list */
1835 pedalroom(); /* make room for "Ped." and "*" if need be */
1837 fixspace(); /* set a width for certain space chords */
1843 * Abstract: Find the effective west boundary of a group.
1845 * Returns: the RW to be used for the group
1847 * Description: This function returns an "effective" RW for the given group.
1848 * Sometimes this is just the true RW. But if the previous chord
1849 * has no groups on this staff that are in danger of colliding, we
1850 * pretend it is a smaller number, so that our group can overlap
1851 * horizonally with previous ones that have no possibly colliding
1856 effwest(mainll_p
, ch_p
, gs_p
)
1858 struct MAINLL
*mainll_p
; /* point at MLL item for this chord */
1859 struct CHORD
*ch_p
; /* point at this chord */
1860 struct GRPSYL
*gs_p
; /* point at this group */
1863 struct CHORD
*pch_p
; /* point at previous chord */
1864 struct CHORD
*ech_p
; /* point at earlier chord */
1865 struct GRPSYL
*pgs_p
; /* point a group in previous chord */
1866 float small
; /* small number to be used */
1867 int found
; /* found a chord with a group on our staff? */
1868 float ourax
; /* tentative value for our chord's AX */
1869 float temp
; /* temp variable */
1872 pch_p
= prevchord(mainll_p
, ch_p
); /* find previous chord */
1874 /* if we are the first chord, return our group's true RW */
1876 return (gs_p
->c
[RW
]);
1878 /* set default to -1.5 stepsize */
1879 small
= -1.5 * STEPSIZE
* svpath(gs_p
->staffno
, STAFFSCALE
)->staffscale
;
1881 /* if already closer to 0 than "small", return true RW */
1882 if (gs_p
->c
[RW
] > small
)
1883 return (gs_p
->c
[RW
]);
1886 * Loop through the previous chord's GRPSYLs to see if it has any
1887 * groups on this staff. If so, return our true RW, if there is a
1888 * danger of collision. If there isn't a group, or it's far enough
1889 * away vertically that we know we won't collide with it, we will leave
1890 * the loop and later return a phony RW.
1892 for (pgs_p
= pch_p
->gs_p
; pgs_p
!= 0; pgs_p
= pgs_p
->gs_p
) {
1893 /* skip cases where there can't be any interference */
1894 if (pgs_p
->staffno
> gs_p
->staffno
)
1895 break; /* nothing more could be on our staff*/
1896 if (pgs_p
->staffno
< gs_p
->staffno
)
1897 continue; /* ignore if wrong staff */
1898 if (pgs_p
->grpsyl
== GS_SYLLABLE
)
1899 continue; /* ignore if not a group */
1900 if (collision_danger(pgs_p
, gs_p
) == NO
)
1903 /* found a group that might collide, return our true RW */
1904 return (gs_p
->c
[RW
]);
1908 * There is no group on our staff in the preceding chord, or at least
1909 * none that we're in danger of colliding with. We'd like to
1910 * let our group overlap into that space if necessary. But there
1911 * might be a group in some earlier chord, and if there are enough dots
1912 * on it, or enough accidentals on our group, they could still
1913 * interfere. Find the first earlier chord, looking right to left,
1914 * that has a group neighboring our group that might collide.
1917 for (ech_p
= prevchord(mainll_p
, pch_p
); ech_p
!= 0;
1918 ech_p
= prevchord(mainll_p
, ech_p
)) {
1920 for (pgs_p
= ech_p
->gs_p
; pgs_p
!= 0; pgs_p
= pgs_p
->gs_p
) {
1922 if (pgs_p
->staffno
> gs_p
->staffno
)
1923 break; /* nothing more could be on our staff*/
1924 if (pgs_p
->staffno
< gs_p
->staffno
)
1925 continue; /* ignore if wrong staff */
1926 if (pgs_p
->grpsyl
== GS_SYLLABLE
)
1927 continue; /* ignore if not a group */
1928 if (collision_danger(pgs_p
, gs_p
) == NO
)
1931 /* found a group that might collide */
1940 pfatal("no preceding group in effwest()");
1943 * Since there could be multiple voices on this staff, there could be
1944 * multiple groups on this staff in the chord we found. Loop through
1945 * each of them, keeping track of the max value our chord's AX would
1946 * have to be to keep our group from overlapping that group.
1949 for ( ; pgs_p
!= 0 && pgs_p
->staffno
== gs_p
->staffno
&&
1950 pgs_p
->grpsyl
== GS_GROUP
; pgs_p
= pgs_p
->gs_p
) {
1952 /* ignore ones that are vertically out of the way */
1953 if (collision_danger(pgs_p
, gs_p
) == NO
)
1956 temp
= ech_p
->c
[AX
] + pgs_p
->c
[RE
] - gs_p
->c
[RW
];
1961 /* find what that value for our AX would make our RW be */
1962 temp
= ch_p
->c
[AW
] - ourax
;
1964 /* return that amount, but not more than "small" */
1965 return (MIN(temp
, small
));
1971 * Abstract: Find the effective east boundary of a group.
1973 * Returns: the RE to be used for the group
1975 * Description: This function returns an "effective" RE for the given group.
1976 * Sometimes this is just the true RE. But if the next chord
1977 * has no groups on this staff that are in danger of colliding, we
1978 * pretend it is a smaller number, so that our group can overlap
1979 * horizonally with the next chord. Don't worry about colliding
1980 * with a group in a later chord; effwest() will handle that when
1981 * processing that later group.
1987 struct CHORD
*ch_p
; /* point at this chord */
1988 struct GRPSYL
*gs_p
; /* point at this group */
1991 struct CHORD
*nch_p
; /* point at next chord */
1992 struct GRPSYL
*ngs_p
; /* point a group in next chord */
1993 float small
; /* small number to be used */
1994 float onestep
; /* a stepsize, scaled */
1997 nch_p
= ch_p
->ch_p
; /* find next chord */
1999 /* if we are the last chord, return our group's true RE */
2001 return (gs_p
->c
[RE
]);
2003 /* set default to 1.5 stepsize */
2004 onestep
= STEPSIZE
* svpath(gs_p
->staffno
, STAFFSCALE
)->staffscale
;
2005 small
= 1.5 * onestep
;
2007 /* if already closer to 0 than "small", return true RE */
2008 if (gs_p
->c
[RE
] < small
)
2009 return (gs_p
->c
[RE
]);
2012 * Loop through the next chord's GRPSYLs to see if it has any
2013 * groups on this staff. If so, return our true RE, unless they are
2014 * not in danger of colliding.
2016 for (ngs_p
= nch_p
->gs_p
; ngs_p
!= 0; ngs_p
= ngs_p
->gs_p
) {
2017 /* skip cases where there can't be any interference */
2018 if (ngs_p
->staffno
> gs_p
->staffno
)
2019 break; /* nothing more could be on our staff*/
2020 if (ngs_p
->staffno
< gs_p
->staffno
)
2021 continue; /* ignore if wrong staff */
2022 if (ngs_p
->grpsyl
== GS_SYLLABLE
)
2023 continue; /* ignore if not a group */
2024 if (collision_danger(gs_p
, ngs_p
) == NO
)
2027 /* found a group that might collide, return true RE */
2028 return (gs_p
->c
[RE
]);
2035 * Name: collision_danger()
2037 * Abstract: Find whether the given groups are in danger of colliding.
2039 * Returns: YES or NO
2041 * Description: This function is given two groups, a left and a right group,
2042 * that are on the same staff. If they are in the same voice, it
2043 * just returns YES (we don't want one note of a voice to go under
2044 * another in the same voice, and it would rarely work anyhow due
2045 * to stem directions). Otherwise it decides whether they are so
2046 * close vertically that they are in danger of colliding unless
2047 * kept apart horizontally.
2051 collision_danger(g1_p
, g2_p
)
2053 struct GRPSYL
*g1_p
; /* ptr to left group */
2054 struct GRPSYL
*g2_p
; /* ptr to right group */
2058 float stepsize
; /* adjusted by staff scale */
2059 float north
[2], south
[2]; /* RN and RS of the groups */
2060 float dotoutside
; /* RY just beyond outside edge of dot*/
2061 float ascent
, descent
; /* of an accidental */
2062 struct GRPSYL
*g_p
[2]; /* point at these two groups */
2063 int k
, j
; /* loop variables */
2064 float accedge
; /* RN or RS of edge of accidental */
2067 /* same voice, always assume collideable */
2068 if (g1_p
->vno
== g2_p
->vno
) {
2072 /* a space can't collide with anything */
2073 if (g1_p
->grpcont
== GC_SPACE
|| g2_p
->grpcont
== GC_SPACE
) {
2077 /* if measure repeat, there won't be anything else to collide with */
2078 if (is_mrpt(g1_p
) || is_mrpt(g2_p
)) {
2082 staffscale
= svpath(g1_p
->staffno
, STAFFSCALE
)->staffscale
;
2083 stepsize
= STEPSIZE
* staffscale
;
2087 /* find the RN and RS of the groups */
2088 for (k
= 0; k
< 2; k
++) {
2089 if (g_p
[k
]->grpcont
== GC_REST
) {
2090 /* for rests, simply use the group boundaries */
2091 north
[k
] = g_p
[k
]->c
[RN
];
2092 south
[k
] = g_p
[k
]->c
[RS
];
2095 * We can't use the group boundaries for notes. For one thing,
2096 * we don't know the stem length yet. Assume the worst, that
2097 * they are way long. It won't usually negatively impact the
2098 * result, nor will the fact that some notes don't have stems,
2099 * because most collisions would be on the non-stem side of the
2100 * groups. On the non-stem side, we can't use the group
2101 * boundary because it includes padding which would often make
2102 * it seem like there'd be a collision, when really there won't
2105 } else if (g_p
[k
]->stemdir
== UP
) {
2107 north
[k
] = 10000.; /* way long stem */
2109 /* one step below lowest note */
2110 south
[k
] = (g_p
[k
]->notelist
[g_p
[k
]->nnotes
-1].
2111 stepsup
- 1) * stepsize
;
2113 /* if dots, and lower than current RS, lower the RS */
2114 if (k
== 0 && g_p
[k
]->dots
> 0) {
2115 dotoutside
= g_p
[k
]->notelist
[g_p
[k
]->nnotes
-1].
2116 ydotr
- 0.6 * stepsize
;
2117 if (dotoutside
< south
[k
]) {
2118 south
[k
] = dotoutside
;
2122 /* if any note has acc going below RS, lower the RS */
2124 for (j
= 0; j
< g_p
[k
]->nnotes
; j
++) {
2125 if (g_p
[k
]->notelist
[j
].accidental
!=
2127 accdimen(&g_p
[k
]->notelist
[j
],
2128 (float *)0, &descent
,
2130 descent
*= staffscale
;
2132 /* bottom edge of acc */
2133 accedge
= stepsize
*
2134 g_p
[k
]->notelist
[j
].stepsup
-
2137 if (accedge
< south
[k
]) {
2144 /* if bottom note has parens, the group boundary shows
2145 * close to how far down they go; extend to there */
2146 if (g_p
[k
]->notelist
[g_p
[k
]->nnotes
-1].note_has_paren
2147 && g_p
[k
]->c
[RS
] < south
[k
]) {
2148 south
[k
] = g_p
[k
]->c
[RS
];
2151 } else { /* stemdir == DOWN */
2153 south
[k
] = -10000.; /* way long stem */
2155 /* one step above highest note */
2156 north
[k
] = (g_p
[k
]->notelist
[0].
2157 stepsup
+ 1) * stepsize
;
2159 /* if dots, and higher than current RN, raise the RN */
2160 if (k
== 0 && g_p
[k
]->dots
> 0) {
2161 dotoutside
= g_p
[k
]->notelist
[0].
2162 ydotr
+ 0.6 * stepsize
;
2163 if (dotoutside
> north
[k
]) {
2164 north
[k
] = dotoutside
;
2168 /* if any note has acc going above RN, raise the RN */
2170 for (j
= 0; j
< g_p
[k
]->nnotes
; j
++) {
2171 if (g_p
[k
]->notelist
[j
].accidental
!=
2173 accdimen(&g_p
[k
]->notelist
[j
],
2174 &ascent
, (float *)0,
2176 ascent
*= staffscale
;
2178 /* top edge of acc */
2179 accedge
= stepsize
*
2180 g_p
[k
]->notelist
[j
].stepsup
+
2183 if (accedge
> north
[k
]) {
2190 /* if top note has parens, the group boundary shows
2191 * close to how far up they go; extend to there */
2192 if (g_p
[k
]->notelist
[0].note_has_paren
2193 && g_p
[k
]->c
[RN
] > north
[k
]) {
2194 north
[k
] = g_p
[k
]->c
[RN
];
2199 /* if the groups don't overlap vertically, no collision danger */
2200 if (south
[0] >= north
[1] || north
[0] <= south
[1]) {
2204 return (YES
); /* collision danger */
2210 * Abstract: Find chord preceding the given one.
2212 * Returns: pointer to previous chord, or 0 if none
2214 * Description: This function is given a pointer to a chord headcell and a
2215 * chord in that list. It finds the preceding chord, returning
2216 * it, or 0 if none. If chord linked lists were doubly linked,
2217 * we wouldn't have to go through this aggravation.
2220 static struct CHORD
*
2221 prevchord(mainll_p
, ch_p
)
2223 struct MAINLL
*mainll_p
; /* ptr to current syllable */
2224 struct CHORD
*ch_p
; /* ptr to current chord */
2227 register struct CHORD
*prevch_p
;
2230 prevch_p
= mainll_p
->u
.chhead_p
->ch_p
; /* get first chord in list */
2232 /* if current chord is first chord, there is none before it */
2233 if (prevch_p
== ch_p
)
2236 /* loop until we find it, then return */
2237 while (prevch_p
->ch_p
!= ch_p
)
2238 prevch_p
= prevch_p
->ch_p
;
2245 * Abstract: Find following syllable if it is in the next chord.
2247 * Returns: pointer to next syllable, or 0 if none
2249 * Description: This function is given a pointer to a syllable, and the chord
2250 * it is in. It looks in the next chord, to see if there is a
2251 * syllable there that follows this syllable. If there is, it
2252 * returns it. Otherwise it returns 0.
2253 * Note: if the next syllable is was given as a space, it counts
2254 * as if it weren't there at all (return 0).
2257 static struct GRPSYL
*
2258 nextchsyl(gs_p
, ch_p
)
2260 struct GRPSYL
*gs_p
; /* ptr to current syllable */
2261 struct CHORD
*ch_p
; /* ptr to current chord */
2264 struct GRPSYL
*nextgs_p
; /* point, looking for next syl */
2267 /* if last chord in measure, return no next syllable */
2268 if (ch_p
->ch_p
== 0)
2272 * Look down next chord until we hit either the end, or the syllable
2273 * that follows the given one. Return what was found.
2275 for (nextgs_p
= ch_p
->ch_p
->gs_p
;
2276 nextgs_p
!= 0 && nextgs_p
!= gs_p
->next
;
2277 nextgs_p
= nextgs_p
->gs_p
)
2280 /* if syl doesn't exist or is a space, return 0 */
2281 if (nextgs_p
== 0 || nextgs_p
->syl
== 0)
2290 * Abstract: Find preceding syllable if it is in the previous chord.
2292 * Returns: pointer to previous syllable, or 0 if none
2294 * Description: This function is given a pointer to a syllable, and the chord
2295 * it is in. It looks in the previous chord, to see if there is a
2296 * syllable there that precedes this syllable. If there is, it
2297 * returns it. Otherwise it returns 0.
2299 * Note: if the prev syllable is given as a space, it counts
2300 * as if it weren't there at all (return 0).
2302 * Also note: unlike nextchsyl, this function compares against
2303 * not only the given GRPSYL, but the also the previous GRPSYL.
2304 * It has to, because it is sometimes called with the previous
2305 * chord, and sometimes with the one before that.
2308 static struct GRPSYL
*
2309 prevchsyl(gs_p
, prevch_p
)
2311 struct GRPSYL
*gs_p
; /* ptr to current syllable */
2312 struct CHORD
*prevch_p
; /* ptr to previous chord */
2315 struct GRPSYL
*prevgs_p
; /* point, looking for next syl */
2318 /* if first chord in measure, return no previous syllable */
2323 * Look down previous chord until we hit either the end, or the syllable
2324 * that precedes the given one. Return what was found.
2325 * "Precede" here means either directly precedes, or precedes in two
2328 for (prevgs_p
= prevch_p
->gs_p
;
2329 prevgs_p
!= 0 && ! (prevgs_p
== gs_p
->prev
||
2330 (gs_p
->prev
!= 0 && prevgs_p
== gs_p
->prev
->prev
));
2331 prevgs_p
= prevgs_p
->gs_p
)
2334 /* if syl doesn't exist or is a space, return 0 */
2335 if (prevgs_p
== 0 || prevgs_p
->syl
== 0)
2344 * Abstract: Increase some chords' width to make room for pedal characters.
2348 * Description: This function tries to make room for "Ped." and "*", so that
2349 * they don't overwrite each other. For each "pedstar" style
2350 * pedal mark, it finds the chord it's closest to. If two of them
2351 * are on neighboring chords, it may widen the left chord to
2352 * provide enough room. The problem is, the best it can do is
2353 * assume that the pedal marks are exactly aligned with their
2354 * closest chords. It doesn't do anything about marks that are
2355 * not on neighboring chords, since that would be quite a bit
2356 * more work and would rarely be necessary. Worst of all, if two
2357 * marks' closest chords are the same chord, nothing can be done.
2364 struct MAINLL
*mainll_p
; /* point at items in main linked list*/
2365 struct CHHEAD
*chhead_p
; /* point at a chord head cell */
2366 struct STAFF
*staff_p
; /* point at a staff */
2367 struct STUFF
*stuff_p
; /* point at a stuff */
2368 struct CHORD
*pedch_p
; /* point at a chord near a pedal mark*/
2369 struct CHORD
*opedch_p
; /* point at prev chord near pedal */
2370 int pedstyle
; /* P_* */
2371 int pedchar
, opedchar
; /* current and previous pedal char */
2372 int font
, size
; /* of a pedal char */
2373 char *string
; /* for pedal char */
2374 float needed
; /* amount of room needed */
2377 debug(16, "pedalroom");
2380 chhead_p
= 0; /* prevent useless 'used before set' warning */
2383 * Loop down the main linked list looking for each chord list headcell.
2385 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
2387 switch (mainll_p
->str
) {
2389 /* need to keep pedstyle and timeden up to date */
2390 asgnssv(mainll_p
->u
.ssv_p
);
2391 continue; /* go to next MLL structure */
2394 /* remember this measure's chord list */
2395 chhead_p
= mainll_p
->u
.chhead_p
;
2396 continue; /* go to next MLL structure */
2399 pedstyle
= svpath(mainll_p
->u
.staff_p
->staffno
,
2400 PEDSTYLE
)->pedstyle
;
2401 if (pedstyle
!= P_LINE
) {
2402 staff_p
= mainll_p
->u
.staff_p
;
2403 break; /* break out and handle this */
2406 continue; /* not pedstar, ignore this staff */
2409 continue; /* skip everything else */
2413 * At this point we are at a staff that has a pedstyle that
2414 * uses "Ped." and "*". Loop down the stuff list, looking for
2417 opedch_p
= 0; /* no pedal mark yet in measure */
2418 opedchar
= '\0';/* prevent useless 'used before set' warning */
2419 for (stuff_p
= staff_p
->stuff_p
; stuff_p
!= 0;
2420 stuff_p
= stuff_p
->next
) {
2422 * If it is not a pedal stuff, or it has no character,
2423 * like a continuation from the previous score, skip.
2425 if (stuff_p
->stuff_type
!= ST_PEDAL
||
2426 stuff_p
->string
== 0)
2429 * Find the chord that is closest to this pedal mark,
2430 * and which character this pedal mark is.
2431 * But following the usual policy of applying "steps"
2432 * offsets only after everything else is done, we
2433 * ignore start.steps and use only start.count.
2435 pedch_p
= closestchord(stuff_p
->start
.count
,
2437 font
= stuff_p
->string
[0];
2438 size
= stuff_p
->string
[1];
2439 string
= stuff_p
->string
+ 2;
2440 pedchar
= next_str_char(&string
, &font
, &size
) & 0xff;
2442 /* if first pedal mark in measure, nothing more to do*/
2443 if (opedch_p
== 0) {
2444 /* remember as previous chord with pedal */
2451 * If this pedal mark and the previous one are by
2452 * neighboring chords, assume these marks are exactly
2453 * aligned with their chords. Make sure the east half
2454 * of the previous chord plus the west half of this
2455 * chord is enough room for them. If it isn't, enlarge
2456 * the east half of the previous chord. (Note: RW is
2457 * negative, so it must be negated.)
2459 if (pedch_p
== opedch_p
->ch_p
) {
2460 needed
= rightped(pedstyle
, opedchar
) +
2461 leftped(pedstyle
, pedchar
);
2462 if (stuff_p
->all
== YES
) {
2463 needed
*= Score
.staffscale
;
2465 needed
*= svpath(staff_p
->staffno
,
2466 STAFFSCALE
)->staffscale
;
2468 if (opedch_p
->c
[RE
] - pedch_p
->c
[RW
] < needed
){
2469 opedch_p
->c
[RE
] = needed
+
2471 opedch_p
->width
= opedch_p
->c
[RE
] -
2476 /* remember previous chord with pedal, and its char */
2484 * Name: closestchord()
2486 * Abstract: Find closest chord to given time value.
2488 * Returns: pointer to the closest chord
2490 * Description: This function finds the CHORD in the given linked list that is
2491 * closest, timewise, to the given count number.
2494 static struct CHORD
*
2495 closestchord(count
, firstch_p
)
2497 double count
; /* which count of the measure */
2498 struct CHORD
*firstch_p
; /* first CHORD in this measure */
2501 RATIONAL reqtime
; /* time requested */
2502 struct CHORD
*ch_p
; /* point along chord list */
2503 struct CHORD
*och_p
; /* (old) point along chord list */
2506 /* if at or before the first count, it's closest to first group */
2510 /* get requested time to nearest tiny part of a count, in lowest terms*/
2511 reqtime
.n
= 4 * MAXBASICTIME
* (count
- 1) + 0.5;
2512 reqtime
.d
= 4 * MAXBASICTIME
* Score
.timeden
;
2516 * Loop through the chord list. As soon as a chord starts at or after
2517 * the requested time value, check whether the requested time is closer
2518 * to the new chord's time, or the previous chord's. Return the
2521 for (och_p
= firstch_p
, ch_p
= och_p
->ch_p
; ch_p
!= 0;
2522 och_p
= ch_p
, ch_p
= ch_p
->ch_p
) {
2523 if (GE(ch_p
->starttime
, reqtime
)) {
2524 if (GT( rsub(reqtime
, och_p
->starttime
),
2525 rsub(ch_p
->starttime
, reqtime
) ))
2532 /* requested time is after last chord; return last chord */
2539 * Abstract: Find the size of the right side of a pedstar pedal char.
2543 * Description: This function finds the size of the part of the given pedal
2544 * character (pedstar style) that is to the right of where it
2545 * should be centered.
2549 rightped(pedstyle
, pedchar
)
2551 int pedstyle
; /* pedstar or alt pedstar */
2552 int pedchar
; /* the given char */
2557 return (strwidth(Ped_start
) / 2.0);
2559 if (pedstyle
== P_PEDSTAR
)
2560 return (strwidth(Ped_start
) - ped_offset());
2561 else /* P_ALTPEDSTAR */
2562 return (strwidth(Ped_start
) / 2.0);
2564 return (strwidth(Ped_stop
) / 2.0);
2566 pfatal("bad pedal character passed to rightped()");
2568 return (0); /* to keep lint happy */
2574 * Abstract: Find the size of the left side of a pedstar pedal char.
2578 * Description: This function finds the size of the part of the given pedal
2579 * character (pedstar style) that is to the left of where it
2580 * should be centered.
2584 leftped(pedstyle
, pedchar
)
2586 int pedstyle
; /* pedstar or alt pedstar */
2587 int pedchar
; /* the given char */
2592 return (strwidth(Ped_start
) / 2.0);
2594 if (pedstyle
== P_PEDSTAR
)
2595 return (strwidth(Ped_stop
) + ped_offset());
2596 else /* P_ALTPEDSTAR */
2597 return (strwidth(Ped_start
) / 2.0);
2599 return (strwidth(Ped_stop
) / 2.0);
2601 pfatal("bad pedal character passed to leftped()");
2603 return (0); /* to keep lint happy */
2609 * Abstract: Reset width, if need be, for chords of all spaces.
2613 * Description: This function loops through chord lists, looking for each chord
2614 * that is all spaces (as shown by the fact that its width is 0).
2615 * If any voice has a nonspace during the time value of this
2616 * chord, we reset its width to a very small positive number, to
2617 * prevent abshorz from treating it like it "deserves" no width
2618 * (rather than what its duration would imply).
2625 struct CHORD
*ch_p
; /* point at a chord */
2626 struct MAINLL
*mainll_p
; /* point at items in main linked list*/
2627 struct MAINLL
*m2_p
; /* another pointer down the MLL */
2628 int crunch
; /* should chord be crunched to 0 width*/
2629 int v
; /* voice number, 0 or 1 */
2632 debug(16, "fixspace");
2634 * Loop down the main linked list looking for each chord list headcell.
2636 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
2638 if (mainll_p
->str
!= S_CHHEAD
)
2639 continue; /* skip everything but chord HC */
2642 * Loop through the chord list, looking for all-space chords.
2643 * Skip the first one in the list; we always want that one to
2644 * be crunched to zero width, since there's nothing earlier
2645 * that could extend into it.
2647 for (ch_p
= mainll_p
->u
.chhead_p
->ch_p
->ch_p
; ch_p
!= 0;
2648 ch_p
= ch_p
->ch_p
) {
2650 if (ch_p
->width
!= 0)
2651 continue; /* skip nonspace chord */
2653 crunch
= YES
; /* init to crunch */
2655 /* loop through every staff and every voice in meas */
2656 for (m2_p
= mainll_p
->next
; m2_p
->str
== S_STAFF
;
2657 m2_p
= m2_p
->next
) {
2659 for (v
= 0; v
< MAXVOICES
&& m2_p
->u
.staff_p
->
2660 groups_p
[v
] != 0; v
++) {
2662 /* if voice has nonspace, don't crunch*/
2663 if ( ! hasspace(m2_p
->u
.staff_p
->
2664 groups_p
[v
], ch_p
->starttime
,
2665 radd(ch_p
->starttime
, ch_p
->duration
))){
2675 /* if should not crunch, set nonzero width to stop it */
2677 ch_p
->width
= 0.001;
2679 } /* for every chord in this measure */
2681 } /* looping through MLL, dealing with chord headcells */