2 dot-column.cc -- implement Dot_column
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "dot-column.hh"
18 #include "axis-group-interface.hh"
19 #include "directional-element-interface.hh"
20 #include "dot-column.hh"
21 #include "dot-configuration.hh"
22 #include "dot-formatting-problem.hh"
25 #include "note-head.hh"
26 #include "pointer-group-interface.hh"
28 #include "rhythmic-head.hh"
29 #include "side-position-interface.hh"
30 #include "staff-symbol-referencer.hh"
33 MAKE_SCHEME_CALLBACK (Dot_column
, calc_positioning_done
, 1);
35 Dot_column::calc_positioning_done (SCM smob
)
37 Grob
*me
= unsmob_grob (smob
);
40 Trigger note collision resolution first, since that may kill off
43 if (Grob
*collision
= unsmob_grob (me
->get_object ("note-collision")))
44 (void) collision
->get_property ("positioning-done");
46 me
->set_property ("positioning-done", SCM_BOOL_T
);
49 = extract_grob_array (me
, "dots");
51 vector
<Grob
*> main_heads
;
55 for (vsize i
= 0; i
< dots
.size (); i
++)
57 Grob
*n
= dots
[i
]->get_parent (Y_AXIS
);
58 commonx
= n
->common_refpoint (commonx
, X_AXIS
);
60 if (Grob
*stem
= unsmob_grob (n
->get_object("stem")))
62 commonx
= stem
->common_refpoint (commonx
, X_AXIS
);
64 if (Stem::first_head (stem
) == n
)
65 main_heads
.push_back (n
);
72 extract_grob_set(me
, "side-support-elements", support
);
75 for (vsize i
= 0; i
< main_heads
.size (); i
++)
76 base_x
.unite (main_heads
[i
]->extent (commonx
, X_AXIS
));
78 for (vsize i
= 0; i
< support
.size (); i
++)
82 ss
= Staff_symbol_referencer::staff_space (s
);
84 /* can't inspect Y extent of rest.
86 Rest collisions should wait after line breaking.
89 if (Rest::has_interface (s
))
91 base_x
.unite (s
->extent (commonx
, X_AXIS
));
94 else if (Stem::has_interface (s
))
96 Real y1
= Stem::head_positions (s
)[-get_grob_direction (s
)];
97 Real y2
= y1
+ get_grob_direction (s
) * 7;
103 y
= s
->extent (s
, Y_AXIS
);
106 y
+= Staff_symbol_referencer::get_position (s
);
108 Box
b (s
->extent (commonx
, X_AXIS
), y
);
111 if (Grob
*stem
= unsmob_grob (s
->get_object ("stem")))
115 for (set
<Grob
*>::const_iterator
i(stems
.begin());
116 i
!= stems
.end (); i
++)
119 Stencil flag
= Stem::flag (stem
);
120 if (!flag
.is_empty ())
122 Interval y
= flag
.extent (Y_AXIS
)
124 + Stem::stem_end_position (stem
);
126 Interval x
= stem
->relative_coordinate (commonx
, X_AXIS
)
127 + flag
.extent (X_AXIS
);
129 boxes
.push_back (Box (x
,y
));
133 vector_sort (dots
, position_less
);
134 for (vsize i
= dots
.size (); i
--;)
135 if (!dots
[i
]->is_live ())
136 dots
.erase (dots
.begin () + i
);
138 Dot_formatting_problem
problem (boxes
, base_x
);
140 Dot_configuration
cfg (problem
);
141 for (vsize i
= 0; i
< dots
.size (); i
++)
146 Grob
*note
= dots
[i
]->get_parent (Y_AXIS
);
149 Grob
*stem
= unsmob_grob (note
->get_object ("stem"));
151 dp
.extremal_head_
= Stem::first_head (stem
) == note
;
153 dp
.x_extent_
= note
->extent (commonx
, X_AXIS
);
156 int p
= Staff_symbol_referencer::get_rounded_position (dp
.dot_
);
158 /* icky, since this should go via a Staff_symbol_referencer
159 offset callback but adding a dot overwrites Y-offset. */
160 p
+= (int) robust_scm2double (dp
.dot_
->get_property ("staff-position"), 0.0);
162 if (dp
.extremal_head_
)
163 dp
.dir_
= to_dir (dp
.dot_
->get_property ("direction"));
165 cfg
.remove_collision (p
);
167 if (Staff_symbol_referencer::on_line (dp
.dot_
, p
))
168 cfg
.remove_collision (p
);
171 problem
.register_configuration (cfg
);
173 for (Dot_configuration::const_iterator
i (cfg
.begin ());
174 i
!= cfg
.end (); i
++)
179 Staff_symbol_referencer::set_position (i
->second
.dot_
, i
->first
);
182 me
->translate_axis (cfg
.x_offset () - me
->relative_coordinate (commonx
, X_AXIS
),
188 Dot_column::add_head (Grob
*me
, Grob
*head
)
190 Grob
*d
= unsmob_grob (head
->get_object ("dot"));
193 Side_position_interface::add_support (me
, head
);
195 Pointer_group_interface::add_grob (me
, ly_symbol2scm ("dots"), d
);
196 d
->set_property ("Y-offset", Grob::x_parent_positioning_proc
);
197 // Dot formatting requests the Y-offset, -which- for rests may
198 // trigger post-linebreak callbacks.
199 if (!Rest::has_interface (head
))
200 d
->set_property ("X-offset", Grob::x_parent_positioning_proc
);
201 Axis_group_interface::add_element (me
, d
);
205 ADD_INTERFACE (Dot_column
,
206 "Group dot objects so they form a column, and position"
207 " dots so they do not clash with staff lines.",