2 stencil.cc -- implement Stencil
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
12 #include "font-metric.hh"
14 #include "string-convert.hh"
17 #include "ly-smobs.icc"
25 Stencil::Stencil (Box b
, SCM func
)
32 Stencil::print_smob (SCM
, SCM port
, scm_print_state
*)
34 scm_puts ("#<Stencil ", port
);
35 scm_puts (" >", port
);
40 Stencil::mark_smob (SCM smob
)
42 Stencil
*s
= (Stencil
*) SCM_CELL_WORD_1 (smob
);
46 IMPLEMENT_SIMPLE_SMOBS (Stencil
);
47 IMPLEMENT_TYPE_P (Stencil
, "ly:stencil?");
48 IMPLEMENT_DEFAULT_EQUAL_P (Stencil
);
51 Stencil::extent (Axis a
) const
57 Stencil::is_empty () const
59 return (expr_
== SCM_EOL
60 || dim_
[X_AXIS
].is_empty ()
61 || dim_
[Y_AXIS
].is_empty ());
65 Stencil::expr () const
71 Stencil::extent_box () const
77 Stencil::rotate (Real a
, Offset off
)
79 rotate_degrees (a
* 180/M_PI
, off
);
83 Rotate this stencil around the point ABSOLUTE_OFF.
87 Stencil::rotate_degrees_absolute (Real a
, Offset absolute_off
)
89 const Real x
= absolute_off
[X_AXIS
];
90 const Real y
= absolute_off
[Y_AXIS
];
93 * Build scheme expression (processed in stencil-interpret.cc)
95 /* TODO: by hanwenn 2008/09/10 14:38:56:
96 * in effect, this copies the underlying expression. It might be a
97 * little bit nicer to mirror this in the api, ie. make a
99 * and have Stencil::rotate be an abbrev of
103 expr_
= scm_list_n (ly_symbol2scm ("rotate-stencil"),
104 scm_list_2 (scm_from_double (a
),
105 scm_cons (scm_from_double (x
), scm_from_double (y
))),
106 expr_
, SCM_UNDEFINED
);
109 * Calculate the new bounding box
111 Box shifted_box
= extent_box ();
112 shifted_box
.translate (-absolute_off
);
115 pts
.push_back (Offset (shifted_box
.x ().at(LEFT
), shifted_box
.y ().at(DOWN
)));
116 pts
.push_back (Offset (shifted_box
.x ().at(RIGHT
), shifted_box
.y ().at(DOWN
)));
117 pts
.push_back (Offset (shifted_box
.x ().at(RIGHT
), shifted_box
.y ().at(UP
)));
118 pts
.push_back (Offset (shifted_box
.x ().at(LEFT
), shifted_box
.y ().at(UP
)));
120 const Offset rot
= complex_exp (Offset (0, a
* M_PI
/ 180.0));
122 for (vsize i
= 0; i
< pts
.size (); i
++)
123 dim_
.add_point (pts
[i
] * rot
+ absolute_off
);
127 Rotate this stencil around the point RELATIVE_OFF.
129 RELATIVE_OFF is measured in terms of the extent of the stencil, so
130 -1 = LEFT/DOWN edge, 1 = RIGHT/UP edge.
133 Stencil::rotate_degrees (Real a
, Offset relative_off
)
136 * Calculate the center of rotation
138 const Real x
= extent (X_AXIS
).linear_combination (relative_off
[X_AXIS
]);
139 const Real y
= extent (Y_AXIS
).linear_combination (relative_off
[Y_AXIS
]);
140 rotate_degrees_absolute (a
, Offset (x
, y
));
144 Stencil::translate (Offset o
)
153 || fabs (o
[a
]) > 1e6
)
155 programming_error (String_convert::form_string ("Improbable offset for stencil: %f staff space", o
[a
])
157 + "Setting to zero.");
159 if (strict_infinity_checking
)
160 scm_misc_error (__FUNCTION__
, "Improbable offset.", SCM_EOL
);
165 expr_
= scm_list_n (ly_symbol2scm ("translate-stencil"),
167 expr_
, SCM_UNDEFINED
);
173 Stencil::translate_axis (Real x
, Axis a
)
181 Stencil::add_stencil (Stencil
const &s
)
183 expr_
= scm_list_3 (ly_symbol2scm ("combine-stencil"), s
.expr_
, expr_
);
188 Stencil::set_empty (bool e
)
192 dim_
[X_AXIS
].set_empty ();
193 dim_
[Y_AXIS
].set_empty ();
197 dim_
[X_AXIS
] = Interval (0, 0);
198 dim_
[Y_AXIS
] = Interval (0, 0);
203 Stencil::align_to (Axis a
, Real x
)
208 Interval
i (extent (a
));
209 translate_axis (-i
.linear_combination (x
), a
);
212 /* See scheme Function. */
214 Stencil::add_at_edge (Axis a
, Direction d
, Stencil
const &s
, Real padding
)
216 Interval my_extent
= dim_
[a
];
217 Interval
i (s
.extent (a
));
221 programming_error ("Stencil::add_at_edge: adding empty stencil.");
227 Real offset
= (my_extent
.is_empty () ? 0.0 : my_extent
[d
] - his_extent
)
231 toadd
.translate_axis (offset
, a
);
236 Stencil::in_color (Real r
, Real g
, Real b
) const
238 Stencil
new_stencil (extent_box (),
239 scm_list_3 (ly_symbol2scm ("color"),
240 scm_list_3 (scm_from_double (r
),
242 scm_from_double (b
)),
249 Stencil::translated (Offset z
) const