]> git.donarmstrong.com Git - lilypond.git/blob - lily/hairpin.cc
* lily/lily-guile.cc (robust_scm2double): new function. Use throughout.
[lilypond.git] / lily / hairpin.cc
1 /*
2   hairpin.cc -- implement Hairpin
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "molecule.hh"
10 #include "line-interface.hh"
11 #include "hairpin.hh"
12 #include "spanner.hh"
13 #include "font-interface.hh"
14 #include "dimensions.hh"
15 #include "paper-def.hh"
16 #include "warn.hh"
17 #include "paper-column.hh"
18 #include "lookup.hh"
19
20 MAKE_SCHEME_CALLBACK (Hairpin, brew_molecule, 1);
21
22 SCM
23 Hairpin::brew_molecule (SCM smob) 
24 {
25   Grob *me= unsmob_grob (smob);
26   Spanner *spanner = dynamic_cast<Spanner*> (me);
27
28   SCM s = me->get_grob_property ("grow-direction");
29   if (!is_direction (s))
30     {
31       me->suicide ();
32       return SCM_EOL;
33     }
34   
35   Direction grow_dir = to_dir (s);
36
37
38   /* Ugh, must be same as Text_spanner::brew_molecule.  */
39
40   /*
41     Ugh. property name is not general.
42    */
43   Real padding = gh_scm2double (me->get_grob_property ("if-text-padding"));
44  
45   Drul_array<bool> broken;
46   Drul_array<Item*> bounds ;
47   Direction d = LEFT;
48   do
49     {
50       bounds[d] =spanner->get_bound (d);
51       broken[d] = bounds[d]->break_status_dir () != CENTER;
52     }
53   while (flip (&d) != LEFT);
54
55   Grob *common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS);
56   Drul_array<Real> x_points ;
57   
58   do
59     {
60       Item *b = bounds[d];
61       x_points[d]  = b->relative_coordinate (common, X_AXIS);
62       if (broken [d])
63         {
64           if (d == LEFT)
65             x_points[d] = b->extent (common,X_AXIS)[RIGHT] ;
66         }
67       else
68         {
69           if (dynamic_cast<Paper_column*> (b))
70             {
71               /*
72                 If we're hung on a paper column, that means we're not
73                 adjacent to a text-dynamic, and we may move closer. We
74                 make the padding a little smaller, here.
75               */
76               Interval e =b->extent (common, X_AXIS);
77               if (e.is_empty ())
78                 e = Interval (0,0) + b->relative_coordinate (common, X_AXIS);
79               
80               x_points[d] = e.center () - d  * padding /3; // ugh.
81             }
82           else
83             {
84               Interval e =b->extent (common, X_AXIS);
85               if (!e.is_empty ())
86                 x_points[d] = e[-d] - d*padding;
87             }
88         }
89     }
90   while (flip (&d) != LEFT);
91
92
93   Real width = x_points[RIGHT] - x_points[LEFT];
94
95   if (width < 0)
96     {
97       me->warning (_ ((grow_dir < 0) ? "decrescendo too small"
98                   : "crescendo too small"));
99       width = 0;
100     }
101
102   bool continued = broken[Direction (-grow_dir)];
103   Real height = robust_scm2double (me->get_grob_property ("height"), 0.2);
104
105   Real starth, endh;
106   if (grow_dir < 0)
107     {
108       starth = height;
109       endh = continued ? height/2 : 0.0;
110     }
111   else
112     {
113       starth = continued ? height/2 : 0.0;
114       endh = height;
115     }
116
117   /*
118     should do relative to staff-symbol staff-space?
119    */
120
121   Molecule mol;
122   mol  = Line_interface::line (me,
123                                       Offset (0, starth),
124                                       Offset (width, endh));
125   mol.add_molecule (Line_interface::line (me,
126                                                  Offset (0, -starth),
127                                                  Offset (width, -endh)));
128
129   mol.translate_axis (x_points[LEFT]
130                       - bounds[LEFT]->relative_coordinate (common, X_AXIS),
131                       X_AXIS);
132   return mol.smobbed_copy ();
133 }
134
135
136
137 ADD_INTERFACE (Hairpin, "hairpin-interface",
138   "hairpin crescendo.",
139   "grow-direction height if-text-padding");
140