2 cluster.cc -- implement Cluster
4 source file of the GNU LilyPond music typesetter
6 (c) 2002--2004 Juergen Reuter <reuter@ipd.uka.de>
8 Han-Wen Nienhuys <hanwen@cs.uu.nl>
18 #include "staff-symbol-referencer.hh"
21 #include "interval.hh"
22 #include "paper-def.hh"
27 TODO: Add support for cubic spline segments.
31 brew_cluster_piece (Grob
*me
, Array
<Offset
> bottom_points
, Array
<Offset
> top_points
)
33 Real blotdiameter
= Staff_symbol_referencer::staff_space (me
)/2;
35 Real padding
=robust_scm2double ( me
->get_property ("padding"), 0.0);
37 Offset vpadding
= Offset (0, padding
);
38 Offset hpadding
= Offset (0.5 * blotdiameter
, 0);
39 Offset hvpadding
= 0.5 * hpadding
+ vpadding
;
41 SCM shape_scm
= me
->get_property ("style");
44 if (gh_symbol_p (shape_scm
))
46 shape
= ly_symbol2string (shape_scm
);
50 programming_error ("#'style should be symbol.");
56 Stencil out
= Stencil ();
59 int size
= bottom_points
.size ();
60 if (String::compare (shape
, "leftsided-stairs") == 0)
62 for (int i
= 0; i
< size
- 1; i
++)
65 box
.add_point (bottom_points
[i
] - hvpadding
);
66 box
.add_point (Offset (top_points
[i
+ 1][X_AXIS
],
67 top_points
[i
][Y_AXIS
]) + hvpadding
);
68 out
.add_stencil (Lookup::round_filled_box (box
, blotdiameter
));
71 else if (String::compare (shape
, "rightsided-stairs") == 0)
73 for (int i
= 0; i
< size
- 1; i
++)
76 box
.add_point (Offset (bottom_points
[i
][X_AXIS
],
77 bottom_points
[i
+ 1][Y_AXIS
]) - hvpadding
);
78 box
.add_point (top_points
[i
+ 1] + hvpadding
);
79 out
.add_stencil (Lookup::round_filled_box (box
, blotdiameter
));
82 else if (String::compare (shape
, "centered-stairs") == 0)
84 Real left_xmid
= bottom_points
[0][X_AXIS
];
85 for (int i
= 0; i
< size
- 1; i
++)
88 0.5 * (bottom_points
[i
][X_AXIS
] + bottom_points
[i
+ 1][X_AXIS
]);
90 box
.add_point (Offset (left_xmid
, bottom_points
[i
][Y_AXIS
]) -
92 box
.add_point (Offset (right_xmid
, top_points
[i
][Y_AXIS
]) +
94 out
.add_stencil (Lookup::round_filled_box (box
, blotdiameter
));
95 left_xmid
= right_xmid
;
97 Real right_xmid
= bottom_points
[size
- 1][X_AXIS
];
99 box
.add_point (Offset (left_xmid
, bottom_points
[size
- 1][Y_AXIS
]) -
101 box
.add_point (Offset (right_xmid
, top_points
[size
- 1][Y_AXIS
]) +
103 out
.add_stencil (Lookup::round_filled_box (box
, blotdiameter
));
105 else if (String::compare (shape
, "ramp") == 0)
107 points
.push (bottom_points
[0] - vpadding
+ hpadding
);
108 for (int i
= 1; i
< size
- 1; i
++)
110 points
.push (bottom_points
[i
] - vpadding
);
112 points
.push (bottom_points
[size
- 1] - vpadding
- hpadding
);
113 points
.push (top_points
[size
- 1] + vpadding
- hpadding
);
114 for (int i
= size
- 2; i
> 0; i
--)
116 points
.push (top_points
[i
] + vpadding
);
118 points
.push (top_points
[0] + vpadding
+ hpadding
);
119 out
.add_stencil (Lookup::round_filled_polygon (points
, blotdiameter
));
123 me
->warning (_f ("unknown cluster style `%s'", shape
.to_str0 ()));
128 MAKE_SCHEME_CALLBACK (Cluster
,print
,1);
130 Cluster::print (SCM smob
)
132 Grob
*me
= unsmob_grob (smob
);
134 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
137 me
->programming_error ("Cluster::print (): not a spanner");
141 Item
*left_bound
= spanner
->get_bound (LEFT
);
142 Item
*right_bound
= spanner
->get_bound (RIGHT
);
144 Grob
*commonx
= left_bound
->common_refpoint (right_bound
, X_AXIS
);
145 SCM cols
=me
->get_property ("columns");
147 if (!gh_pair_p (cols
))
149 me
->warning ("junking empty cluster");
155 commonx
= common_refpoint_of_list (cols
, commonx
, X_AXIS
);
156 Grob
* commony
= common_refpoint_of_list (cols
, me
, Y_AXIS
);
157 Array
<Offset
> bottom_points
;
158 Array
<Offset
> top_points
;
161 Real left_coord
= left_bound
->relative_coordinate (commonx
, X_AXIS
);
164 TODO: should we move the cluster a little to the right to be in
165 line with the center of the note heads?
168 for (SCM s
= cols
; gh_pair_p (s
); s
= ly_cdr (s
))
170 Grob
* col
= unsmob_grob (ly_car (s
));
171 Interval yext
= col
->extent (commony
, Y_AXIS
);
173 Real x
= col
->relative_coordinate (commonx
, X_AXIS
) - left_coord
;
174 bottom_points
.push (Offset (x
, yext
[DOWN
]));
175 top_points
.push (Offset (x
, yext
[UP
]));
179 Across a line break we anticipate on the next pitches.
181 if (spanner
->original_
)
183 Spanner
*orig
= dynamic_cast<Spanner
*> (spanner
->original_
);
185 if (spanner
->get_break_index () < orig
->broken_intos_
.size ()-1)
187 Spanner
* next
= orig
->broken_intos_
[spanner
->get_break_index () + 1];
188 SCM cols
= next
->get_property ("columns");
189 if (gh_pair_p (cols
))
191 Grob
*next_commony
= common_refpoint_of_list (cols
, next
, Y_AXIS
);
192 Grob
* col
= unsmob_grob (ly_car (scm_last_pair (cols
)));
194 Interval v
= col
->extent (next_commony
, Y_AXIS
);
195 Real x
= right_bound
->relative_coordinate (commonx
, X_AXIS
) - left_coord
;
197 bottom_points
.insert (Offset (x
, v
[DOWN
]),0);
198 top_points
.insert (Offset (x
, v
[UP
]),0);
203 bottom_points
.reverse ();
204 top_points
.reverse ();
206 Stencil out
= brew_cluster_piece (me
, bottom_points
, top_points
);
207 out
.translate_axis (- me
->relative_coordinate (commony
, Y_AXIS
), Y_AXIS
);
208 return out
.smobbed_copy ();
211 ADD_INTERFACE (Cluster
,"cluster-interface",
212 "A graphically drawn musical cluster. "
214 "@code{padding} adds to the vertical extent of the shape (top and "
216 "The property @code{style} controls the shape of cluster segments. Valid values "
217 "include @code{leftsided-stairs}, @code{rightsided-stairs}, @code{centered-stairs}, "
220 "style padding columns");
224 struct Cluster_beacon
227 DECLARE_SCHEME_CALLBACK (height
, (SCM
, SCM
));
228 static bool has_interface (Grob
*);
231 MAKE_SCHEME_CALLBACK (Cluster_beacon
,height
,2);
233 Cluster_beacon::height (SCM g
, SCM ax
)
235 Grob
*me
= unsmob_grob (g
);
237 Interval v
= robust_scm2interval (me
->get_property ("positions"), Interval (0,0));
238 return ly_interval2scm (Staff_symbol_referencer::staff_space (me
) * 0.5 * v
);
243 ADD_INTERFACE(Cluster_beacon
,
244 "cluster-beacon-interface",
245 "A place holder for the cluster spanner to determine the vertical "
246 "extents of a cluster spanner at this X position.",