]> git.donarmstrong.com Git - lilypond.git/blob - lily/lyric-extender.cc
2003 -> 2004
[lilypond.git] / lily / lyric-extender.cc
1 /*
2   lyric-extender.cc -- implement Lyric_extender
3   source file of the GNU LilyPond music typesetter
4
5   (c) 1998--2004 Jan Nieuwenhuizen <janneke@gnu.org>
6   Han-Wen Nienhuys
7 */
8
9 #include <math.h>
10
11 #include "box.hh"
12 #include "warn.hh"
13 #include "lookup.hh"
14 #include "molecule.hh"
15 #include "paper-column.hh"
16 #include "paper-def.hh"
17 #include "lyric-extender.hh"
18 #include "note-head.hh"
19 #include "group-interface.hh"
20
21
22 bool
23 Lyric_extender::is_visible (Grob *gr)
24 {
25   Spanner*me = dynamic_cast<Spanner*> (gr);
26
27   SCM heads = me->get_grob_property ("heads");
28   int l = scm_ilength (heads);
29   if (l == 0)
30     return false;
31   
32   return true;
33 }
34
35 MAKE_SCHEME_CALLBACK (Lyric_extender,brew_molecule,1)
36 SCM 
37 Lyric_extender::brew_molecule (SCM smob) 
38 {
39   Spanner *me = unsmob_spanner (smob);
40   Item *l = me->get_bound (LEFT);
41   Item *r = me->get_bound (RIGHT);
42   Grob *common = l->common_refpoint (r, X_AXIS);
43   
44
45   Real sl = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));  
46
47   Link_array<Grob> heads (Pointer_group_interface__extract_grobs (me, (Grob*)0,
48                                                                   "heads"));
49
50   if (!heads.size () && r->break_status_dir () == CENTER)
51     return SCM_EOL;
52
53   common = common_refpoint_of_array (heads, common, X_AXIS);
54   
55   Real left_point = 0.0;
56   if (l->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
57     left_point = l->extent (common, X_AXIS)[RIGHT];
58   else
59     left_point = heads[0]->extent (common, X_AXIS)[LEFT];
60
61   if (isinf (left_point))
62     return SCM_EOL;
63
64   /*
65     It seems that short extenders are even lengthened to go past the
66     note head, but haven't found a pattern in it yet. --hwn 1/1/04
67     
68    */
69   SCM minlen =  me->get_grob_property ("minimum-length");
70   Real right_point
71     = left_point + (robust_scm2double  (minlen,0));
72
73   Spanner *orig = dynamic_cast<Spanner*> (me->original_);
74   bool last_line = orig
75     && (me->get_break_index () == orig->broken_intos_.size() - 2)
76     && !Lyric_extender::is_visible (orig->broken_intos_.top ());
77     
78
79   if (heads.size ())
80     right_point = right_point >? heads.top ()->extent (common, X_AXIS)[RIGHT];
81
82   Real h = sl * robust_scm2double (me->get_grob_property ("thickness"), 0);
83   Real pad = 2* h;
84
85   if (!r->break_status_dir ())
86     right_point = right_point <? (r->extent (common, X_AXIS)[LEFT] - pad);
87   else if (!last_line)
88     {
89       /*
90         run to end of line.
91        */
92       right_point = right_point >? (r->extent (common, X_AXIS)[LEFT] - pad);
93     }
94   
95   if (isinf (right_point))
96     {
97       programming_error ("Right point of extender not defined?");
98       right_point = r->relative_coordinate (common, X_AXIS);
99     }  
100
101   left_point += pad;
102
103   Real w = right_point - left_point;
104
105   if (w < 1.5 * h)
106     return SCM_EOL;
107   
108   Molecule  mol (Lookup::round_filled_box (Box (Interval (0,w), Interval (0,h)),
109                                            0.8 * h));
110   mol.translate_axis (left_point - me->relative_coordinate (common, X_AXIS), X_AXIS);
111   return mol.smobbed_copy ();
112 }
113
114
115 ADD_INTERFACE (Lyric_extender,"lyric-extender-interface",
116   "The extender is a simple line at the baseline of the lyric "
117   " that helps show the length of a melissima (tied/slurred note).",
118   "thickness heads");