]> git.donarmstrong.com Git - lilypond.git/blob - lily/molecule.cc
710ee8b397298b6bad669b8c3510bb9c8ad46578
[lilypond.git] / lily / molecule.cc
1 /*
2   molecule.cc -- implement Molecule
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "interval.hh"
10 #include "string.hh"
11 #include "molecule.hh"
12 #include "atom.hh"
13 #include "debug.hh"
14
15 #include "killing-cons.tcc"
16
17 #ifdef ATOM_SMOB
18 #define MOL_EOL SCM_EOL
19 #define NEXT_CELL(a) gh_cdr(a)
20 #define CELLTYPE SCM
21 #define UNBOX_ATOM(a) Atom::atom_l (a)
22 #define BOX_ATOM(a) a->make_smob ()
23 #define NEWCELL(a,b) gh_cons (a,b)
24 #define UNBOX_PTR(a) gh_car (a)
25 #else
26 #define MOL_EOL 0
27 #define NEXT_CELL(a) ptr->next_
28 #define CELLTYPE Cons<Atom>*
29 #define UNBOX_ATOM(a) a
30 #define UNBOX_PTR(a) a->car_
31 #define BOX_ATOM(a) a
32 #define NEWCELL(a,b) new Killing_cons<Atom>(a,b)
33 #endif
34
35 Box
36 Molecule::extent() const
37 {
38   return dim_;
39 }
40
41 Interval
42 Molecule::extent(Axis a) const
43 {
44   return dim_[a];
45 }
46
47 void
48 Molecule::translate (Offset o)
49 {
50   for (CELLTYPE ptr = atom_list_; ptr != MOL_EOL; ptr = NEXT_CELL(ptr))
51     {
52       UNBOX_ATOM(UNBOX_PTR(ptr))->off_ += o;
53     }
54   if (!empty_b ())
55     dim_.translate (o);
56 }
57
58 void
59 Molecule::translate_axis (Real x,Axis a)
60 {
61   for (CELLTYPE  ptr = atom_list_; ptr != MOL_EOL; ptr = NEXT_CELL(ptr))
62     UNBOX_ATOM (UNBOX_PTR(ptr))->off_[a] += x;
63
64   if (!dim_[a].empty_b ())
65     dim_[a] += x;
66 }
67
68 void
69 Molecule::add_molecule (Molecule const &m)
70 {
71   for (CELLTYPE  ptr = m.atom_list_; ptr != MOL_EOL; ptr = NEXT_CELL(ptr))
72     add_atom(UNBOX_ATOM (UNBOX_PTR(ptr)));
73   
74   dim_.unite (m.dim_);
75 }
76
77 void
78 Molecule::add_atom (Atom const *al)
79 {
80   Atom *a = new Atom(*al);
81
82   atom_list_ = NEWCELL(BOX_ATOM(a), atom_list_);
83 }
84
85 void
86 Molecule::operator=(Molecule const & src)
87 {
88   if (&src == this) return;
89
90 #ifndef ATOM_SMOB
91   delete atom_list_;
92 #endif
93
94   atom_list_ = MOL_EOL;
95   dim_= src.dim_;
96   add_molecule (src);
97 }
98
99 void
100 Molecule::set_empty (bool e)
101 {
102   if (e)
103     {
104       dim_[X_AXIS].set_empty ();
105       dim_[Y_AXIS].set_empty ();
106     }
107   else
108     {
109       dim_[X_AXIS] = Interval(0,0);
110       dim_[Y_AXIS] = Interval (0,0);
111     }
112 }
113
114 Molecule::Molecule (Molecule const &s)
115 {
116   atom_list_ = MOL_EOL;
117   set_empty (true);
118   add_molecule (s);
119 }
120
121 Molecule::~Molecule ()
122 {
123 #ifndef ATOM_SMOB
124   delete atom_list_;
125 #endif
126 }
127
128 void
129 Molecule::print() const
130 {
131 #ifndef NPRINT
132   if (! flower_dstream)
133     return;
134   DEBUG_OUT << "dim:";
135   for (Axis i=X_AXIS; i < NO_AXES; incr (i))
136     DEBUG_OUT << axis_name_str (i) << " = " << dim_[i].str ();
137 #endif
138 }
139
140 void
141 Molecule::align_to (Axis a, Direction d)
142 {
143   if (d == CENTER)
144     {
145       Interval i (extent (a));
146       translate_axis (-i.center (), a);
147     }
148   else
149     {
150       translate_axis (-extent (a)[d], a);
151     }
152 }
153
154 Molecule::Molecule ()
155 {
156   dim_[X_AXIS].set_empty ();
157   dim_[Y_AXIS].set_empty ();
158   atom_list_ = MOL_EOL;
159 }
160
161
162 void
163 Molecule::add_at_edge (Axis a, Direction d, Molecule const &m, Real padding)
164 {
165   Real my_extent= empty_b () ? 0.0 : dim_[a][d];
166   Interval i (m.extent ()[a]);
167   if (i.empty_b ())
168     programming_error ("Molecule::add_at_edge: adding empty molecule.");
169   
170   Real his_extent = i[-d];
171   Real offset = my_extent -  his_extent;
172   Molecule toadd (m);
173   toadd.translate_axis (offset + d * padding, a);
174   add_molecule (toadd);
175 }
176
177 bool
178 Molecule::empty_b () const
179 {
180   return atom_list_ == MOL_EOL;
181 }