]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest-collision.cc
release: 1.3.33
[lilypond.git] / lily / rest-collision.cc
1 /*
2   rest-collision.cc -- implement Rest_collision
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include <math.h>               // ceil.
9
10 #include "beam.hh"
11 #include "debug.hh"
12 #include "rest-collision.hh"
13 #include "note-column.hh"
14 #include "stem.hh"
15 #include "note-head.hh"
16 #include "collision.hh"
17 #include "paper-def.hh"
18 #include "rest.hh"
19 #include "group-interface.hh"
20 #include "staff-symbol-referencer.hh"
21
22 void
23 Rest_collision::add_column (Note_column *nc_l)
24 {
25   add_dependency (nc_l);
26   Group_interface gi (this);  
27   if (nc_l->rest_b ())
28     gi.name_ = "rests";
29   else
30     gi.name_ = "notes";
31   
32   gi.add_element (nc_l);
33 }
34
35 void
36 Rest_collision::before_line_breaking ()
37 {
38   Link_array<Note_column> rest_l_arr =
39     Group_interface__extract_elements (this, (Note_column*) 0, "rests");
40   Link_array<Note_column> ncol_l_arr =
41     Group_interface__extract_elements (this, (Note_column*) 0, "notes");
42                                       
43   
44   /* 
45      handle rest-rest and rest-note collisions
46
47      [todo]
48      * decide not to print rest if too crowded?
49
50      * ignore rests under beams.
51    */
52
53   // no rests to collide
54   if (!rest_l_arr.size())
55     return;
56
57   // no partners to collide with
58   if (rest_l_arr.size() + ncol_l_arr.size () < 2)
59     return;
60
61   // meisjes met meisjes
62   if (!ncol_l_arr.size()) 
63     {
64       /*
65         UGH.  Should get dims from table.  Should have minimum dist.
66        */
67       int dy = rest_l_arr.size() > 2 ? 6 : 4;
68         
69       rest_l_arr[0]->translate_rests (rest_l_arr[0]->dir () *dy);       
70       rest_l_arr.top()->translate_rests (rest_l_arr.top ()->dir ()* dy);
71     }
72   // meisjes met jongetjes
73   else 
74     {
75       if (rest_l_arr.size () > 1)
76         {
77           warning (_("too many colliding rests"));
78         }
79       if (ncol_l_arr.size () > 1)
80         {
81           warning (_("too many notes for rest collision"));
82         }
83       Note_column * rcol = rest_l_arr[0];
84
85       // try to be opposite of noteheads. 
86       Direction dir = - ncol_l_arr[0]->dir();
87
88       Interval restdim = rcol->rest_dim ();
89       if (restdim.empty_b ())
90         return;
91       
92       // staff ref'd?
93       Real staff_space = paper_l()->get_var ("interline");
94
95         /* FIXME
96           staff_space =  rcol->rest_l_arr[0]->staff_space ();
97         */
98       Real half_staff_space_f = staff_space/2;
99       Real minimum_dist = paper_l ()->get_var ("restcollision_minimum_dist")
100         * half_staff_space_f;
101       
102       /*
103         assumption: ref points are the same. 
104        */
105       Interval notedim;
106       for (int i = 0; i < ncol_l_arr.size(); i++) 
107         {
108           notedim.unite (ncol_l_arr[i]->extent (Y_AXIS));
109         }
110
111       Interval inter (notedim);
112       inter.intersect (restdim);
113
114       Real dist =
115         minimum_dist +  dir * (notedim[dir] - restdim[-dir]) >? 0;
116
117
118       // FIXME
119       //int stafflines = 5; // rcol->rest_l_arr[0]->line_count;
120       int stafflines = Staff_symbol_referencer_interface (this).line_count ();
121       // hurg?
122       stafflines = stafflines != 0 ? stafflines : 5;
123       
124       // move discretely by half spaces.
125       int discrete_dist = int (ceil (dist / (0.5 *staff_space)));
126
127       // move by whole spaces inside the staff.
128       if (discrete_dist < stafflines+1)
129         discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
130       
131       rcol->translate_rests (dir * discrete_dist);
132     }
133 }
134
135
136 Rest_collision::Rest_collision()
137 {
138   set_elt_property ("rests", SCM_EOL);
139   set_elt_property ("notes", SCM_EOL);
140   set_elt_property ("transparent", SCM_BOOL_T);
141   set_empty (X_AXIS);
142   set_empty (Y_AXIS);
143 }
144