]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column.cc
* lily/tie-column.cc (set_manual_tie_configuration): new function.
[lilypond.git] / lily / tie-column.cc
1 /*
2   tie-column.cc -- implement Tie_column
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "tie-column.hh"
10
11 #include <cmath>
12
13 #include "skyline.hh"
14 #include "warn.hh"
15 #include "paper-column.hh"
16 #include "spanner.hh"
17 #include "pointer-group-interface.hh"
18 #include "tie.hh"
19 #include "directional-element-interface.hh"
20 #include "tie-column-format.hh"
21
22 using namespace std;
23
24 void
25 Tie_column::add_tie (Grob *me, Grob *tie)
26 {
27   if (tie->get_parent (Y_AXIS)
28       && Tie_column::has_interface (tie->get_parent (Y_AXIS)))
29     return;
30
31   if (!Pointer_group_interface::count (me, ly_symbol2scm ("ties")))
32     {
33       dynamic_cast<Spanner *> (me)->set_bound (LEFT, Tie::head (tie, LEFT));
34       dynamic_cast<Spanner *> (me)->set_bound (RIGHT, Tie::head (tie, RIGHT));
35     }
36
37   tie->set_parent (me, Y_AXIS);
38   Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), tie);
39   tie->add_dependency (me);
40 }
41
42 void
43 Tie_column::set_directions (Grob *me)
44 {
45   if (!to_boolean (me->get_property ("positioning-done")))
46     {
47       me->set_property ("positioning-done", SCM_BOOL_T); 
48       new_directions (me);
49     }
50 }
51
52
53
54 MAKE_SCHEME_CALLBACK (Tie_column, after_line_breaking, 1);
55 SCM
56 Tie_column::after_line_breaking (SCM smob)
57 {
58   set_directions (unsmob_grob (smob));
59   return SCM_UNSPECIFIED;
60 }
61
62 /*
63   Extend the spanner over its Tie constituents.
64 */
65 MAKE_SCHEME_CALLBACK (Tie_column, before_line_breaking, 1);
66 SCM
67 Tie_column::before_line_breaking (SCM smob)
68 {
69   Spanner *me = dynamic_cast<Spanner *> (unsmob_grob (smob));
70   for (SCM s = me->get_property ("ties"); scm_is_pair (s); s = scm_cdr (s))
71     {
72       Spanner *tie = dynamic_cast<Spanner *> (unsmob_grob (scm_car (s)));
73       Direction dir = LEFT;
74       do
75         {
76           if (dir * tie->get_bound (dir)->get_column ()->get_rank ()
77               > dir * me->get_bound (dir)->get_column ()->get_rank ())
78             me->set_bound (dir, Tie::head (tie, dir));
79         }
80       while (flip (&dir) != LEFT);
81     }
82   return SCM_UNSPECIFIED;
83 }
84
85
86 void
87 Tie_column::new_directions (Grob *me)
88 {
89   extract_grob_set (me, "ties", ro_ties);
90   Link_array<Grob> ties (ro_ties);
91   if (!ties.size ())
92     return;
93
94   if (ties.size() == 1)
95     {
96       Tie::set_default_control_points (ties[0]);
97       return;
98     }
99   
100   ties.sort (&Tie::compare);
101
102   Array<Tie_configuration> tie_configs;
103   for (int i = 0; i < ties.size (); i++)
104     {
105       Tie_configuration conf;
106       conf.dir_ = get_grob_direction (ties[i]);
107       conf.position_ = Tie::get_position (ties[i]);
108       tie_configs.push (conf);
109     }
110
111   SCM manual_configs = me->get_property ("tie-configuration");
112   bool manual_override = false;
113   set_manual_tie_configuration (&tie_configs,
114                                 &manual_override,
115                                 manual_configs);
116   set_tie_config_directions (&tie_configs);
117
118   Grob *common = me;
119   for (int i = 0; i < ties.size (); i++)
120     {
121       common = dynamic_cast<Spanner*> (ties[i])->get_bound (LEFT)->common_refpoint (common, X_AXIS); 
122       common = dynamic_cast<Spanner*> (ties[i])->get_bound (RIGHT)->common_refpoint (common, X_AXIS); 
123     }
124
125   Drul_array< Array<Skyline_entry> > skylines;
126   set_chord_outlines (&skylines, ties, common);
127   
128   Tie_details details;
129   details.init (ties[0]);
130
131   /*
132     Let the ties flow out, according to our single-tie formatting.
133    */
134   if (!manual_override)
135     {
136       Tie::get_configuration (ties[0], common, &tie_configs.elem_ref (0),
137                               &skylines,
138                               details
139                               );
140       Tie::get_configuration (ties.top (), common,
141                               &tie_configs.elem_ref (tie_configs.size()-1),
142                               &skylines,
143                               details
144                               );
145     }
146
147   /*
148     Calculate final width and shape of the ties.
149    */
150   for (int i = 0; i < ties.size(); i++)
151     {
152       if (!manual_override
153           && (i == 0 || i == ties.size () -1))
154         continue;
155
156
157       final_shape_adjustment (tie_configs[i],
158                               skylines,
159                               ties[0],
160                               details);
161     }
162
163   
164   /*
165     Try to shift small ties into available spaces.
166    */
167   if (!manual_override)
168     {
169       shift_small_ties (&tie_configs, ties[0], details);
170     }
171   
172   for (int i = 0; i < ties.size(); i++)
173     {
174       Tie::set_control_points (ties[i], common, tie_configs[i],
175                                details
176                                );
177       set_grob_direction (ties[i], tie_configs[i].dir_);
178     }
179 }
180
181
182
183 ADD_INTERFACE (Tie_column, "tie-column-interface",
184                "Object that sets directions of multiple ties in a tied chord",
185
186                /* properties */
187                "positioning-done "
188                "tie-configuration "
189                );
190