]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column.cc
* lily/include/tie-formatting-problem.hh (class
[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@xs4all.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 #include "tie-formatting-problem.hh"
22
23 using namespace std;
24
25 void
26 Tie_column::add_tie (Grob *me, Grob *tie)
27 {
28   if (tie->get_parent (Y_AXIS)
29       && Tie_column::has_interface (tie->get_parent (Y_AXIS)))
30     return;
31
32   if (!Pointer_group_interface::count (me, ly_symbol2scm ("ties")))
33     {
34       dynamic_cast<Spanner *> (me)->set_bound (LEFT, Tie::head (tie, LEFT));
35       dynamic_cast<Spanner *> (me)->set_bound (RIGHT, Tie::head (tie, RIGHT));
36     }
37
38   tie->set_parent (me, Y_AXIS);
39   Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), tie);
40 }
41
42 /*
43   Extend the spanner over its Tie constituents.
44 */
45 MAKE_SCHEME_CALLBACK (Tie_column, before_line_breaking, 1);
46 SCM
47 Tie_column::before_line_breaking (SCM smob)
48 {
49   Spanner *me = dynamic_cast<Spanner *> (unsmob_grob (smob));
50   for (SCM s = me->get_property ("ties"); scm_is_pair (s); s = scm_cdr (s))
51     {
52       Spanner *tie = dynamic_cast<Spanner *> (unsmob_grob (scm_car (s)));
53       Direction dir = LEFT;
54       do
55         {
56           if (dir * tie->get_bound (dir)->get_column ()->get_rank ()
57               > dir * me->get_bound (dir)->get_column ()->get_rank ())
58             me->set_bound (dir, Tie::head (tie, dir));
59         }
60       while (flip (&dir) != LEFT);
61     }
62   
63   return SCM_UNSPECIFIED;
64 }
65
66 MAKE_SCHEME_CALLBACK(Tie_column, calc_positioning_done, 1)
67 SCM
68 Tie_column::calc_positioning_done (SCM smob)
69 {
70   Grob *me = unsmob_grob (smob);
71   extract_grob_set (me, "ties", ro_ties);
72   Link_array<Grob> ties (ro_ties);
73   if (!ties.size ())
74     return SCM_BOOL_T;
75
76   if (ties.size() == 1)
77     {
78       /*
79         Already handled by standard mechanisms.
80        */
81       return SCM_BOOL_T;
82     }
83   
84   ties.sort (&Tie::compare);
85
86   Ties_configuration ties_config;
87   for (int i = 0; i < ties.size (); i++)
88     {
89       Tie_configuration conf;
90       if (scm_is_number (ties[i]->get_property_data (ly_symbol2scm ("direction"))))
91         conf.dir_ = get_grob_direction (ties[i]);
92       conf.position_ = Tie::get_position (ties[i]);
93       ties_config.ties_.push (conf);
94     }
95
96   SCM manual_configs = me->get_property ("tie-configuration");
97   bool manual_override = false;
98   set_manual_tie_configuration (&ties_config,
99                                 &manual_override,
100                                 manual_configs);
101   set_tie_config_directions (&ties_config);
102
103   Tie_formatting_problem problem;
104   problem.from_ties (ties);
105   
106   Tie_details details;
107   details.init (ties[0]);
108
109   /*
110     Let the ties flow out, according to our single-tie formatting.
111    */
112   if (!manual_override)
113     {
114       Tie::get_configuration (ties[0], &ties_config.ties_.elem_ref (0),
115                               problem,
116                               details);
117       Tie::get_configuration (ties.top (), 
118                               &ties_config.ties_.elem_ref (ties_config.ties_.size()-1),
119                               problem,
120                               details
121                               );
122     }
123
124   /*
125     Calculate final width and shape of the ties.
126    */
127   for (int i = 0; i < ties.size(); i++)
128     {
129       if (!manual_override
130           && (i == 0 || i == ties.size () -1))
131         continue;
132
133
134       final_shape_adjustment (ties_config.ties_[i],
135                               problem,
136                               ties[0],
137                               details);
138     }
139
140   
141   /*
142     Try to shift small ties into available spaces.
143    */
144   if (!manual_override)
145     {
146       shift_small_ties (&ties_config, ties[0], details);
147     }
148   
149   for (int i = 0; i < ties.size(); i++)
150     {
151       Tie::set_control_points (ties[i], problem.common_x_refpoint (), ties_config.ties_[i],
152                                details
153                                );
154       set_grob_direction (ties[i], ties_config.ties_[i].dir_);
155     }
156   return SCM_BOOL_T;
157 }
158
159
160
161 ADD_INTERFACE (Tie_column, "tie-column-interface",
162                "Object that sets directions of multiple ties in a tied chord",
163
164                /* properties */
165                "positioning-done "
166                "tie-configuration "
167                );
168