]> git.donarmstrong.com Git - lilypond.git/blob - lily/stencil.cc
* lily/global-context.cc (run_iterator_on_me): fix grace note
[lilypond.git] / lily / stencil.cc
1 /*
2   stencil.cc -- implement Stencil
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include <math.h>
10 #include <libc-extension.hh>    // isinf
11
12 #include "font-metric.hh" 
13 #include "dimensions.hh"
14 #include "interval.hh"
15 #include "string.hh"
16 #include "stencil.hh"
17 #include "warn.hh"
18
19 #include "ly-smobs.icc"
20
21
22 Offset
23 Stencil::origin () const
24 {
25   return origin_;
26 }
27
28 Interval
29 Stencil::extent (Axis a) const
30 {
31   return dim_[a];
32 }
33
34 Stencil::Stencil (Box b, SCM func)
35 {
36   expr_ = func;
37   dim_ = b;
38 }
39
40 Stencil::Stencil ()
41 {
42   expr_ = SCM_EOL;
43   set_empty (true);
44 }
45
46 void
47 Stencil::translate (Offset o)
48 {
49   Axis a = X_AXIS;
50   while (a < NO_AXES)
51     {
52       if (abs (o[a]) > 100 CM
53           || isinf (o[a]) || isnan (o[a]))
54         {
55           programming_error ("Improbable offset for translation: setting to zero");
56           o[a] =  0.0;
57         }
58       incr (a);
59     }
60
61   expr_ = scm_list_n (ly_symbol2scm ("translate-stencil"),
62                       ly_offset2scm (o),
63                       expr_, SCM_UNDEFINED);
64   if (!is_empty ())
65     dim_.translate (o);
66   origin_ += o;
67 }
68   
69 void
70 Stencil::translate_axis (Real x, Axis a)
71 {
72   Offset o (0,0);
73   o[a] = x;
74   translate (o);
75 }
76
77 void
78 Stencil::add_stencil (Stencil const &s)
79 {
80   expr_ = scm_list_n (ly_symbol2scm ("combine-stencil"),
81                       s.expr_, expr_, SCM_UNDEFINED);
82   dim_.unite (s.dim_);
83 }
84
85 void
86 Stencil::set_empty (bool e)
87 {
88   if (e)
89     {
90       dim_[X_AXIS].set_empty ();
91       dim_[Y_AXIS].set_empty ();
92     }
93   else
94     {
95       dim_[X_AXIS] = Interval (0,0);
96       dim_[Y_AXIS] = Interval (0,0);
97     }
98 }
99
100 void
101 Stencil::align_to (Axis a, Real x)
102 {
103   if (is_empty ())
104     return ;
105
106   Interval i (extent (a));
107   translate_axis (-i.linear_combination (x), a);
108 }
109
110 /*
111   TODO: unintuitive naming, you would expect *this to be moved.  Kept
112   API for compat with add_at_edge ().
113 */
114 Stencil
115 Stencil::moved_to_edge (Axis a, Direction d, Stencil const &s, Real padding,
116                         Real minimum) const
117 {
118   Real my_extent= is_empty () ? 0.0 : dim_[a][d];
119   Interval i (s.extent (a));
120   Real his_extent;
121   if (i.is_empty ())
122     {
123       programming_error ("Stencil::move_to_edge: adding empty stencil.");
124       his_extent = 0.0;
125     }
126   else
127     his_extent = i[-d];
128
129   Real offset = (my_extent -  his_extent) + d * padding;
130
131   Stencil toadd (s);
132   toadd.translate_axis (offset,a);
133
134   if (minimum > 0
135       && d *(- origin ()[a] + toadd.origin ()[a]) < minimum)
136     toadd.translate_axis ( -toadd.origin ()[a]
137                            + origin ()[a] + d* minimum, a);
138     
139   return toadd;
140 }
141
142 /*  See scheme Function.  */
143 void
144 Stencil::add_at_edge (Axis a, Direction d, Stencil const &s, Real padding,
145                        Real minimum)
146 {
147   add_stencil (moved_to_edge (a,d,s,padding, minimum));
148 }
149
150 /* Hmm... maybe this is not such a good idea ; stuff can be empty,
151    while expr_ == '()  */
152 bool
153 Stencil::is_empty () const
154 {
155   return expr_ == SCM_EOL;
156 }
157
158 SCM
159 Stencil::get_expr () const
160 {
161   return expr_;
162 }
163
164 Box
165 Stencil::extent_box () const
166 {
167   return dim_;
168 }
169
170 int
171 Stencil::print_smob (SCM , SCM port, scm_print_state *)
172 {
173   scm_puts ("#<Stencil ", port);
174   scm_puts (" >", port);
175   return 1;
176 }
177
178 SCM
179 Stencil::mark_smob (SCM s)
180 {
181   Stencil  *r = (Stencil *) ly_cdr (s);
182   return r->expr_;
183 }
184
185 IMPLEMENT_SIMPLE_SMOBS (Stencil);
186 IMPLEMENT_TYPE_P (Stencil, "ly:stencil?");
187 IMPLEMENT_DEFAULT_EQUAL_P (Stencil);