]> git.donarmstrong.com Git - lilypond.git/blob - lily/tie-column-format.cc
* lily/include/tie-formatting-problem.hh (class
[lilypond.git] / lily / tie-column-format.cc
1 /*
2   tie-column-format.cc -- implement formatting routines for Tie_column
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "stem.hh"
11 #include "note-head.hh"
12 #include "tie.hh"
13 #include "parray.hh"
14 #include "spanner.hh"
15 #include "item.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "directional-element-interface.hh"
18 #include "rhythmic-head.hh"
19 #include "tie-formatting-problem.hh"
20
21 #include <set>
22
23 void
24 set_manual_tie_configuration (Ties_configuration *ties_config,
25                               bool *manual_override,
26                               SCM manual_configs
27                               )
28 {
29   *manual_override = false;
30   int k = 0;
31   for (SCM s = manual_configs;
32        scm_is_pair (s) && k < ties_config->ties_.size(); s = scm_cdr (s))
33     {
34       SCM entry = scm_car (s);
35       if (!scm_is_pair (entry))
36         continue;
37
38       *manual_override = true;
39       Tie_configuration &conf = ties_config->ties_.elem_ref (k);
40       
41       Real complete_pos = robust_scm2double (scm_car (entry),
42                                              conf.position_);
43
44       conf.position_ = int (rint (complete_pos));
45       conf.delta_y_ = complete_pos - conf.position_;
46       conf.dir_ = Direction (robust_scm2int (scm_cdr (entry),
47                                              conf.dir_));
48       k ++;
49     }
50 }
51
52 void
53 shift_small_ties (Ties_configuration *tie_configs,
54                   Grob *staff_referencer,
55                   Tie_details const &details)
56 {
57   set<int> positions_taken;
58   for (int i = 0; i < tie_configs->ties_.size (); i++)
59     positions_taken.insert (int (rint (tie_configs->ties_.elem (i).position_)));
60
61   for (int i = 0; i < tie_configs->ties_.size (); i++)
62     {
63       Tie_configuration * conf = &tie_configs->ties_.elem_ref (i);
64
65       /*
66         on staff line and small enough, translate a little further 
67       */
68       Real h = conf->height (details);
69       bool next_free = positions_taken.find (int (rint (conf->position_ + conf->dir_)))
70         == positions_taken.end ();
71
72       int rounded_pos = int (rint (conf->position_ + conf->delta_y_ / details.staff_space_));
73       bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer, rounded_pos);
74       
75       if (next_free)
76         if (on_line && h < 0.4 * details.staff_space_)
77           {
78             positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
79             conf->delta_y_ += 0.2 * details.staff_space_ * conf->dir_;
80           }
81         else if (!on_line && h > 0.6 * details.staff_space_)
82           {
83             positions_taken.insert (int (rint (conf->position_ + conf->dir_)));
84             conf->delta_y_ += 0.5 * details.staff_space_ * conf->dir_;
85           }
86     }
87 }
88
89
90 void
91 final_shape_adjustment (Tie_configuration &conf,
92                         Tie_formatting_problem const &problem,
93                         Grob *staff_referencer,
94                         Tie_details const &details)
95 {
96   Real line_dy = 0.0;
97   bool on_line = Staff_symbol_referencer::on_staffline (staff_referencer,
98                                                         int (rint (conf.position_)));
99   if (on_line)
100     line_dy = - sign (conf.height (details) - 0.6 * details.staff_space_)
101       * 0.2 * details.staff_space_ * conf.dir_;
102
103   Real y = conf.position_ * details.staff_space_ * 0.5
104     + line_dy;
105   
106   conf.attachment_x_ = problem.get_attachment (y);
107   conf.attachment_x_.intersect (problem.get_attachment (y + conf.dir_ * details.staff_space_ * 0.5));
108
109   conf.delta_y_ += line_dy;
110   conf.attachment_x_.widen (-details.x_gap_);
111   if (!on_line
112       && Staff_symbol_referencer::staff_radius (staff_referencer) * details.staff_space_ > y)
113     conf.center_tie_vertically (details);
114 }
115
116 void
117 set_tie_config_directions (Ties_configuration *tie_configs_ptr)
118 {
119   Array<Tie_configuration> &tie_configs (tie_configs_ptr->ties_);
120   
121   if (!tie_configs[0].dir_)
122     tie_configs[0].dir_ = DOWN;
123   if (!tie_configs.top().dir_)
124     tie_configs.top().dir_ = UP;
125
126   /*
127     Seconds
128    */
129   for (int i = 1; i < tie_configs.size(); i++)
130     {
131       Real diff = tie_configs[i-1].position_
132         - tie_configs[i].position_;
133       
134       if (fabs (diff) <= 1)
135         {
136           if (!tie_configs[i-1].dir_)
137             tie_configs[i-1].dir_ = DOWN;
138           if (!tie_configs[i].dir_)
139             tie_configs[i].dir_ = UP;
140         }
141     }
142
143   for (int i = 1; i < tie_configs.size() - 1; i++)
144     {
145       Tie_configuration &conf = tie_configs.elem_ref (i);
146       if (conf.dir_)
147         continue;
148
149       Direction position_dir =
150         Direction (sign (conf.position_));
151       if (!position_dir)
152         position_dir = DOWN;
153
154       conf.dir_ = position_dir;
155     }
156 }
157