2 stencil.cc -- implement Stencil
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2007 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 RELATIVE_OFF.
85 RELATIVE_OFF is measured in terms of the extent of the stencil, so
86 -1 = LEFT/DOWN edge, 1 = RIGHT/UP edge.
89 Stencil::rotate_degrees (Real a
, Offset relative_off
)
91 const Real x_cen
= extent (X_AXIS
).center ();
92 const Real y_cen
= extent (Y_AXIS
).center ();
95 * Calculate the center of rotation
97 const Real x
= x_cen
+ relative_off
[X_AXIS
] * x_cen
;
98 const Real y
= y_cen
+ relative_off
[Y_AXIS
] * y_cen
;
101 * Build scheme expression (processed in stencil-interpret.cc)
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
112 pts
.push_back (Offset (-x_cen
, -y_cen
));
113 pts
.push_back (Offset (x_cen
, -y_cen
));
114 pts
.push_back (Offset (x_cen
, y_cen
));
115 pts
.push_back (Offset (-x_cen
, y_cen
));
117 const Offset rot
= complex_exp (Offset (0, a
* M_PI
/ 180.0));
119 for (vsize i
= 0; i
< pts
.size (); i
++)
120 dim_
.add_point (pts
[i
] * rot
+ Offset (x_cen
, y_cen
));
124 Stencil::translate (Offset o
)
133 || fabs (o
[a
]) > 1e6
)
135 programming_error (String_convert::form_string ("Improbable offset for stencil: %f staff space", o
[a
])
137 + "Setting to zero.");
139 if (strict_infinity_checking
)
140 scm_misc_error (__FUNCTION__
, "Improbable offset.", SCM_EOL
);
145 expr_
= scm_list_n (ly_symbol2scm ("translate-stencil"),
147 expr_
, SCM_UNDEFINED
);
153 Stencil::translate_axis (Real x
, Axis a
)
161 Stencil::add_stencil (Stencil
const &s
)
163 expr_
= scm_list_3 (ly_symbol2scm ("combine-stencil"), s
.expr_
, expr_
);
168 Stencil::set_empty (bool e
)
172 dim_
[X_AXIS
].set_empty ();
173 dim_
[Y_AXIS
].set_empty ();
177 dim_
[X_AXIS
] = Interval (0, 0);
178 dim_
[Y_AXIS
] = Interval (0, 0);
183 Stencil::align_to (Axis a
, Real x
)
188 Interval
i (extent (a
));
189 translate_axis (-i
.linear_combination (x
), a
);
192 /* See scheme Function. */
194 Stencil::add_at_edge (Axis a
, Direction d
, Stencil
const &s
, Real padding
)
196 Interval my_extent
= dim_
[a
];
197 Interval
i (s
.extent (a
));
201 programming_error ("Stencil::add_at_edge: adding empty stencil.");
207 Real offset
= (my_extent
.is_empty () ? 0.0 : my_extent
[d
] - his_extent
)
211 toadd
.translate_axis (offset
, a
);
216 Stencil::in_color (Real r
, Real g
, Real b
) const
218 Stencil
new_stencil (extent_box (),
219 scm_list_3 (ly_symbol2scm ("color"),
220 scm_list_3 (scm_from_double (r
),
222 scm_from_double (b
)),
229 Stencil::translated (Offset z
) const