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