]> git.donarmstrong.com Git - lilypond.git/blob - lily/text-spanner.cc
9b4bcadaab64f1f55e5cbfd41778bf95f57a88a9
[lilypond.git] / lily / text-spanner.cc
1 /*
2   text-spanner.cc -- implement Text_spanner
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2003 Jan Nieuwenhuizen <janneke@gnu.org>
7
8   Revised over good by Han-Wen. 
9 */
10
11 #include "molecule.hh"
12 #include "text-item.hh"
13 #include "text-spanner.hh"
14 #include "line-spanner.hh"
15 #include "spanner.hh"
16 #include "font-interface.hh"
17 #include "dimensions.hh"
18 #include "paper-def.hh"
19 #include "warn.hh"
20 #include "paper-column.hh"
21 #include "staff-symbol-referencer.hh"
22
23 /*
24   TODO:
25   - vertical start / vertical end (fixme-name) |
26   - contination types (vert. star, vert. end)  |-> eat volta-bracket
27   - more styles
28   - more texts/positions
29 */
30
31 MAKE_SCHEME_CALLBACK (Text_spanner, brew_molecule, 1);
32
33 /*
34   TODO: this function is too long
35
36
37 */
38 SCM
39 Text_spanner::brew_molecule (SCM smob) 
40 {
41   Grob *me= unsmob_grob (smob);
42   Spanner *spanner = dynamic_cast<Spanner*> (me);
43   
44   /* Ugh, must be same as Hairpin::brew_molecule.  */
45   Real padding = 0.0;
46   SCM itp= me->get_grob_property ("if-text-padding");
47   if (gh_number_p (itp))
48     padding = gh_scm2double (itp);
49
50   Grob *common = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), X_AXIS);
51   Paper_def * paper = me->get_paper();
52
53   SCM flare = me->get_grob_property ("bracket-flare");
54   SCM shorten = me->get_grob_property ("shorten-pair");
55
56   Interval span_points;
57   Drul_array<bool> broken;
58   Direction d = LEFT;
59   do
60     {
61       Item *b = spanner->get_bound (d);
62       broken[d] = b->break_status_dir () != CENTER;
63
64       if (broken[d])
65         {
66           if (d == LEFT)
67             span_points[d] = spanner->get_broken_left_end_align ();
68           else
69             span_points[d] = b->relative_coordinate (common, X_AXIS);
70         }
71       else
72           {
73             bool encl = to_boolean (me->get_grob_property ("enclose-bounds"));
74             span_points[d] = b->extent (common, X_AXIS)[encl ? d : -d];
75
76             if (is_number_pair (shorten))
77               span_points -= d * gh_scm2double (index_get_cell (shorten, d));
78           }
79       
80       if (is_number_pair (flare))
81         span_points -= d * gh_scm2double (index_get_cell (flare, d));
82     }
83   while (flip (&d) != LEFT);
84
85
86   SCM properties = Font_interface::font_alist_chain (me);
87   SCM edge_text = me->get_grob_property ("edge-text");
88   Drul_array<Molecule> edge;
89   if (gh_pair_p (edge_text))
90     {
91       Direction d = LEFT;
92       do
93         {
94           if (!to_boolean (me->get_grob_property ("text-repeat-if-broken"))
95               && broken[d])
96             continue;
97           
98           SCM text = index_get_cell (edge_text, d);
99
100           if (Text_item::markup_p (text)) 
101             edge[d] = *unsmob_molecule (Text_item::interpret_markup (paper->self_scm (), properties, text));
102           
103           if (!edge[d].is_empty ())
104             edge[d].align_to (Y_AXIS, CENTER);
105         }
106       while (flip (&d) != LEFT);
107     }
108
109   Real thick = paper->get_realvar (ly_symbol2scm ("linethickness"));  
110   SCM st = me->get_grob_property ("thickness");
111   if (gh_number_p (st))
112     {
113       thick *=  gh_scm2double (st);
114     }
115   
116   Drul_array<Real> edge_height = robust_scm2interval (me->get_grob_property ("edge-height"),
117                                                       Interval (1.0, 1.0));
118   Drul_array<Molecule> edge_line;
119     {
120       Direction d = LEFT;
121       int dir = to_dir (me->get_grob_property ("direction"));
122       do
123         {
124           if (broken[d])
125             continue;
126           
127           Real dx = 0.0;
128           if (gh_pair_p (flare))
129             dx = gh_scm2double (index_get_cell (flare, d)) * d;
130
131           Real dy = - dir * edge_height[d] ;
132           if (dy)
133             edge_line[d] = Line_spanner::line_molecule (me, thick, Offset(0,0),
134                                                         Offset (dx, dy));
135         }
136       while (flip (&d) != LEFT);
137     }
138   
139   Molecule m;
140   do
141     {
142       Interval ext = edge[d].extent (X_AXIS);
143       if (!ext.is_empty ())
144         {
145           edge[d].translate_axis (span_points[d], X_AXIS);
146           m.add_molecule (edge[d]);
147           span_points[d] += -d *  ext[-d];
148         }
149     }
150   while (flip (&d) != LEFT);
151   do
152     {
153       if (d* span_points[d] > d * edge[-d].extent(X_AXIS)[d])
154         {
155           edge_line[d].translate_axis (span_points[d], X_AXIS);
156           m.add_molecule (edge_line[d]);
157         }
158     }
159   while (flip (&d) != LEFT);
160
161   if (!span_points.is_empty ())
162     {
163       Molecule l =Line_spanner::line_molecule (me, thick,
164                                                Offset (span_points[LEFT], 0),
165                                                Offset (span_points[RIGHT], 0));
166       m.add_molecule (l);
167     }
168   m.translate_axis (- me->relative_coordinate (common, X_AXIS), X_AXIS);
169   return m.smobbed_copy ();
170 }
171
172
173
174
175 ADD_INTERFACE (Text_spanner,"text-spanner-interface",
176                "generic text spanner",
177                "text-repeat-if-broken dash-period if-text-padding dash-fraction edge-height bracket-flare edge-text shorten-pair style thickness enclose-bounds width-correct");
178