2 cluster.cc -- implement Cluster
4 source file of the GNU LilyPond music typesetter
6 (c) 2002--2003 Juergen Reuter <reuter@ipd.uka.de>
15 #include "staff-symbol-referencer.hh"
18 #include "interval.hh"
19 #include "paper-def.hh"
20 #include "paper-column.hh"
23 * TODO: Add support for cubic spline segments.
26 brew_cluster_piece (Grob
*me
, Array
<Offset
> bottom_points
, Array
<Offset
> top_points
)
29 Real blotdiameter
= me
->get_paper ()->get_var ("blotdiameter");
31 Real blotdiameter
= Staff_symbol_referencer::staff_space (me
)/2;
35 SCM padding_scm
= me
->get_grob_property ("padding");
36 if (gh_number_p (padding_scm
))
37 padding
= gh_scm2double (padding_scm
);
40 Offset vpadding
= Offset (0, padding
);
41 Offset hpadding
= Offset (0.5 * blotdiameter
, 0);
42 Offset hvpadding
= 0.5 * hpadding
+ vpadding
;
44 SCM shape_scm
= me
->get_grob_property ("shape");
46 if (gh_symbol_p (shape_scm
))
48 shape
= ly_symbol2string (shape_scm
);
52 shape
= "leftsided-stairs";
56 Molecule out
= Molecule ();
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_molecule (Lookup::roundfilledbox (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_molecule (Lookup::roundfilledbox (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_molecule (Lookup::roundfilledbox (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_molecule (Lookup::roundfilledbox (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_molecule (Lookup::round_filled_polygon (points
, blotdiameter
));
123 me
->warning (_f ("unknown cluster shape `%s'", shape
.to_str0 ()));
128 MAKE_SCHEME_CALLBACK (Cluster
,brew_molecule
,1);
130 Cluster::brew_molecule (SCM smob
)
132 Grob
*me
= unsmob_grob (smob
);
134 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
137 me
->programming_error ("Cluster::brew_molecule(): not a spanner");
141 Item
*left_bound
= spanner
->get_bound (LEFT
);
142 Item
*right_bound
= spanner
->get_bound (RIGHT
);
143 bool right_broken
= right_bound
->break_status_dir () != CENTER
;
145 Grob
*common
= left_bound
->common_refpoint (right_bound
, X_AXIS
);
148 Array
<Offset
> bottom_points
;
149 Array
<Offset
> top_points
;
150 bottom_points
.clear ();
152 SCM column_scm
= SCM_EOL
;
154 SCM columns_scm
= me
->get_grob_property ("segments");
155 if (columns_scm
== SCM_EOL
)
157 me
->warning ("junking empty cluster");
162 columns_scm
!= SCM_EOL
;
163 columns_scm
= ly_cdr (columns_scm
)) {
164 column_scm
= ly_car (columns_scm
);
165 SCM col_scm
= ly_car (column_scm
);
166 if (gh_number_p (col_scm
))
167 // broken spanner: this column not in this piece
169 continue; // still have to expect columns
171 break; // ok, we have seen all columns
172 column
= unsmob_grob (col_scm
);
173 column_scm
= ly_cdr (column_scm
);
174 Real y_bottom
= gh_scm2double (ly_car (column_scm
));
175 column_scm
= ly_cdr (column_scm
);
176 Real y_top
= gh_scm2double (ly_car (column_scm
));
177 Real x
= column
->relative_coordinate (common
, X_AXIS
);
179 x
-= left_bound
->relative_coordinate (common
, X_AXIS
);
180 bottom_points
.push (Offset (x
, y_bottom
));
181 top_points
.push (Offset (x
, y_top
));
185 Real y_bottom
= gh_scm2double (ly_car (column_scm
));
186 column_scm
= ly_cdr (column_scm
);
187 Real y_top
= gh_scm2double (ly_car (column_scm
));
188 column_scm
= ly_cdr (column_scm
);
190 right_bound
->relative_coordinate (common
, X_AXIS
) -
191 left_bound
->relative_coordinate (common
, X_AXIS
);
192 bottom_points
.push (Offset (x
, y_bottom
));
193 top_points
.push (Offset (x
, y_top
));
195 Molecule out
= brew_cluster_piece (me
, bottom_points
, top_points
);
196 return out
.smobbed_copy ();
199 ADD_INTERFACE (Cluster
,"cluster-interface",
200 "A graphically drawn musical cluster.",
201 "shape padding segments");