]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-column.cc
Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / lily / paper-column.cc
1 /*
2   paper-column.cc -- implement Paper_column
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "paper-column.hh"
10
11 #include "moment.hh"
12 #include "paper-score.hh"
13 #include "warn.hh"
14 #include "axis-group-interface.hh"
15 #include "spaceable-grob.hh"
16 #include "text-interface.hh"
17 #include "lookup.hh"
18 #include "font-interface.hh"
19 #include "output-def.hh"
20 #include "pointer-group-interface.hh"
21 #include "grob-array.hh"
22 #include "system.hh"
23 #include "spring.hh"
24 #include "lookup.hh"
25
26 Grob *
27 Paper_column::clone (int count) const
28 {
29   return new Paper_column (*this, count);
30 }
31
32 void
33 Paper_column::do_break_processing ()
34 {
35   Item::do_break_processing ();
36 }
37
38 int
39 Paper_column::get_rank (Grob const *me)
40 {
41   return dynamic_cast<Paper_column const *> (me)->rank_;
42 }
43
44 System *
45 Paper_column::get_system () const
46 {
47   return system_;
48 }
49
50 void
51 Paper_column::set_system (System *s)
52 {
53   system_ = s;
54 }
55
56 Paper_column *
57 Paper_column::get_column () const
58 {
59   return (Paper_column *) (this);
60 }
61
62 Paper_column::Paper_column (SCM l, Object_key const *key)
63   : Item (l, key)               // guh.?
64 {
65   system_ = 0;
66   rank_ = -1;
67 }
68
69 Paper_column::Paper_column (Paper_column const &src, int count)
70   : Item (src, count)
71 {
72   system_ = 0;
73   rank_ = src.rank_;
74 }
75
76 int
77 Paper_column::compare (Grob * const &a,
78                        Grob * const &b)
79 {
80   return sign (dynamic_cast<Paper_column*> (a)->rank_
81                - dynamic_cast<Paper_column*> (b)->rank_);
82 }
83
84 bool
85 Paper_column::less_than (Grob *const &a,
86                          Grob *const &b)
87 {
88   Paper_column *pa = dynamic_cast<Paper_column*> (a);
89   Paper_column *pb = dynamic_cast<Paper_column*> (b);
90   
91   return pa->rank_ < pb->rank_;
92 }
93
94 Moment
95 Paper_column::when_mom (Grob *me)
96 {
97   SCM m = me->get_property ("when");
98   if (Moment *when = unsmob_moment (m))
99     return *when;
100   return Moment (0);
101 }
102
103 bool
104 Paper_column::is_musical (Grob *me)
105 {
106   SCM m = me->get_property ("shortest-starter-duration");
107   Moment s (0);
108   if (unsmob_moment (m))
109     s = *unsmob_moment (m);
110   return s != Moment (0);
111 }
112
113 bool
114 Paper_column::is_used (Grob *me)
115 {
116   extract_grob_set (me, "elements", elts);
117   if (elts.size ())
118     return true;
119
120   extract_grob_set (me, "bounded-by-me", bbm);
121   if (bbm.size ())
122     return true;
123   
124   if (Paper_column::is_breakable (me))
125     return true;
126
127   if (to_boolean (me->get_property ("used")))
128     return true;
129   return false;
130 }
131
132 bool
133 Paper_column::is_breakable (Grob *me)
134 {
135   return scm_is_symbol (me->get_property ("line-break-permission"));
136 }
137
138 /*
139   Print a vertical line and  the rank number, to aid debugging.
140 */
141 MAKE_SCHEME_CALLBACK (Paper_column, print, 1);
142 SCM
143 Paper_column::print (SCM p)
144 {
145   Paper_column *me = dynamic_cast<Paper_column*> (unsmob_grob (p));
146
147   string r = to_string (Paper_column::get_rank (me));
148
149   Moment *mom = unsmob_moment (me->get_property ("when"));
150   string when = mom ? mom->to_string () : "?/?";
151
152   Font_metric *musfont = Font_interface::get_default_font (me);
153   SCM properties = Font_interface::text_font_alist_chain (me);
154
155   SCM scm_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
156                                                   properties,
157                                                   ly_string2scm (r));
158   SCM when_mol = Text_interface::interpret_markup (me->layout ()->self_scm (),
159                                                    properties,
160                                                    ly_string2scm (when));
161   Stencil t = *unsmob_stencil (scm_mol);
162   t.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (when_mol), 0.1, 0.1);
163   t.align_to (X_AXIS, CENTER);
164   t.align_to (Y_AXIS, DOWN);
165
166   Stencil l = Lookup::filled_box (Box (Interval (-0.01, 0.01),
167                                        Interval (-2, -1)));
168
169
170   
171   System * my_system = me->get_system ();
172   int drank =
173     me->get_rank ()
174     - my_system->get_bound (LEFT)->get_column ()->get_rank ();
175   int j = 0;
176   for (SCM s = me->get_object ("ideal-distances");
177        scm_is_pair (s); s = scm_cdr (s))
178     {
179       Spring_smob *sp = unsmob_spring (scm_car (s));
180       
181       Real y = -j * 0.1 -3;
182       vector<Offset> pts;
183       pts.push_back (Offset (0, y));
184
185       Offset p2 (sp->distance_, y);
186       pts.push_back (p2);
187       
188       Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
189       Stencil head (musfont->find_by_name ("arrowheads.open.01"));
190       head.translate (p2);
191       id_stencil.add_stencil (head);
192       id_stencil = id_stencil.in_color (0,0,1);
193       l.add_stencil (id_stencil) ;
194      
195     }
196    
197   for (SCM s = me->get_object ("minimum-distances");
198        scm_is_pair (s); s = scm_cdr (s))
199     {
200       Grob *other  = unsmob_grob (scm_caar (s));
201       Real dist = scm_to_double (scm_cdar (s));
202
203       Real y = -j * 0.1 -3.5;
204       vector<Offset> pts;
205       pts.push_back (Offset (0, y));
206
207       Offset p2 (dist, y);
208       pts.push_back (p2);
209
210       Stencil id_stencil = Lookup::points_to_line_stencil (0.1, pts);
211       Stencil head (musfont->find_by_name ("arrowheads.open.0M1"));
212       head.translate_axis (y, Y_AXIS);
213       id_stencil.add_stencil (head);
214       
215       id_stencil = id_stencil.in_color (1,0,0);
216       l.add_stencil (id_stencil);
217     }
218   t.add_stencil (l);
219   return t.smobbed_copy ();
220 }
221
222 /*
223   This is all too hairy. We use bounded-by-me to make sure that some
224   columns are kept "alive". Unfortunately, when spanners are suicided,
225   this falls apart again, because suicided spanners are still in
226   bounded-by-me
227
228   THIS IS BROKEN KLUDGE. WE SHOULD INVENT SOMETHING BETTER.
229 */
230 MAKE_SCHEME_CALLBACK (Paper_column, before_line_breaking, 1);
231 SCM
232 Paper_column::before_line_breaking (SCM grob)
233 {
234   Grob *me = unsmob_grob (grob);
235
236   SCM bbm = me->get_object ("bounded-by-me");
237   Grob_array *ga = unsmob_grob_array (bbm);
238   if (!ga)
239     return SCM_UNSPECIFIED;
240
241   vector<Grob*> &array (ga->array_reference ());
242
243   for (vsize i = array.size (); i--;)
244     {
245       Grob *g = array[i];
246
247       if (!g || !g->is_live ())
248         /* UGH . potentially quadratic. */
249         array.erase (array.begin () + i);
250     }
251
252   return SCM_UNSPECIFIED;
253 }
254
255
256 ADD_INTERFACE (Paper_column,
257                "@code{Paper_column} objects form the top-most X-parents for items."
258                "  The are two types of columns: musical columns, where are attached to, and "
259                "  non-musical columns, where bar-lines, clefs etc. are attached to. "
260                "  The spacing engine determines the X-positions of these objects."
261                
262                "\n\n"
263                "They are\n"
264                "  numbered, the first (leftmost) is column 0. Numbering happens before\n"
265                "  line-breaking, and columns are not renumbered after line breaking.\n"
266                "  Since many columns go unused, you should only use the rank field to\n"
267                "  get ordering information.  Two adjacent columns may have\n"
268                "  non-adjacent numbers.\n",
269                
270
271                /* properties */
272                "between-cols "
273                "bounded-by-me "
274                "grace-spacing " 
275                "line-break-system-details "
276                "line-break-penalty "
277                "line-break-permission "
278                "page-break-penalty "
279                "page-break-permission "
280                "page-turn-penalty "
281                "page-turn-permission "
282                "rhythmic-location "
283                "shortest-playing-duration "
284                "shortest-starter-duration "
285                "spacing "
286                "used "
287                "when ");
288