]> git.donarmstrong.com Git - lilypond.git/blob - lily/nested-system-start-delimiter.cc
* lily/side-position-interface.cc (aligned_side): multiply
[lilypond.git] / lily / nested-system-start-delimiter.cc
1 /*
2   system-start-delimiter.cc -- implement Nested_system_start_delimiter
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "system-start-delimiter.hh"
10 #include "spanner.hh"
11 #include "axis-group-interface.hh"
12 #include "output-def.hh"
13 #include "font-interface.hh"
14 #include "all-font-metrics.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "lookup.hh"
17 #include "item.hh"
18
19 #include "pointer-group-interface.hh"
20
21
22 struct Nested_system_start_delimiter
23 {
24 public:
25   bool has_interface (Grob *);
26   Stencil static make_substencil (Spanner *, Grob *, SCM, SCM, SCM);
27   DECLARE_SCHEME_CALLBACK (print, (SCM));
28 };
29
30 Link_array<Grob> 
31 flatten_hierarchy (SCM hier)
32 {
33   Link_array<Grob> retval;
34   if (unsmob_grob (hier))
35     retval.push (unsmob_grob (hier));
36   
37   if (scm_is_pair (hier))
38     {
39       retval = flatten_hierarchy (scm_car (hier));
40       retval.concat (flatten_hierarchy (scm_cdr (hier)));
41     }
42   
43   return retval;
44 }
45
46
47 Stencil
48 Nested_system_start_delimiter::make_substencil (Spanner *me,
49                                              Grob *common,
50                                              SCM hierarchy,
51                                              SCM depth_styles,
52                                              SCM default_style
53                                              )
54 {
55   Interval ext;
56   Link_array<Grob> elts = flatten_hierarchy (hierarchy);
57
58   if (elts.is_empty ())
59     return Stencil();
60   
61   int non_empty_count = 0;
62   for (int i = elts.size (); i--;)
63     {
64       Spanner *sp = dynamic_cast<Spanner *> (elts[i]);
65
66       if (sp
67           && sp->get_bound (LEFT) == me->get_bound (LEFT))
68         {
69           Interval dims = sp->extent (common, Y_AXIS);
70           if (!dims.is_empty ())
71             {
72               non_empty_count ++;
73               ext.unite (dims);
74             }
75         }
76     }
77
78   SCM glyph_sym = ly_symbol2scm ("bracket");
79   if (scm_is_pair (depth_styles))
80     glyph_sym = scm_car (depth_styles);
81   
82   if (ext.is_empty ()
83       || (robust_scm2double (me->get_property ("collapse-height"), 0.0) >= ext.length()))
84     {
85       return Stencil();
86     }
87
88   Stencil total;
89
90   Real len = ext.length ();
91   if (glyph_sym == ly_symbol2scm ("bracket"))
92     total = System_start_delimiter::staff_bracket (me, len);
93   else if (glyph_sym == ly_symbol2scm ("brace"))
94     total = System_start_delimiter::staff_brace (me, len);
95   else if (glyph_sym == ly_symbol2scm ("bar-line"))
96     total = System_start_delimiter::simple_bar (me, len);
97   else if (glyph_sym == ly_symbol2scm ("line-bracket"))
98     total = System_start_delimiter::line_bracket (me, len);
99
100   total.translate_axis (ext.center (), Y_AXIS);
101
102   Real left_x = total.extent (X_AXIS)[LEFT];
103   for (SCM s = hierarchy; scm_is_pair (s); s = scm_cdr (s))
104     {
105       SCM entry = scm_car (s);
106
107       if (scm_is_pair (entry)
108           && !scm_is_symbol (scm_car (entry)))
109         {
110           Stencil sub = make_substencil (me, common, entry,
111                                          scm_is_pair (depth_styles)
112                                          ? scm_cdr (depth_styles) : SCM_EOL,
113                                          default_style);
114           sub.translate_axis (left_x, X_AXIS);
115           total.add_stencil (sub);
116         }
117     }
118
119   return total;
120 }
121
122 MAKE_SCHEME_CALLBACK (Nested_system_start_delimiter, print, 1);
123 SCM
124 Nested_system_start_delimiter::print (SCM smob)
125 {
126   Spanner *me = unsmob_spanner (smob);
127   if (!me)
128     return SCM_EOL;
129
130   SCM hierarchy = me->get_object ("staff-hierarchy");
131   Link_array<Grob> elts = flatten_hierarchy (hierarchy);
132   Grob *common = common_refpoint_of_array (elts, me, Y_AXIS);
133
134   SCM default_style = me->get_property ("style");
135   if (!scm_is_symbol (default_style))
136     default_style = ly_symbol2scm ("line-bracket"); 
137   
138   Stencil total = make_substencil (me, common, hierarchy, me->get_property ("styles"),
139                                    default_style);
140   total.translate_axis (- me->relative_coordinate (common, Y_AXIS), Y_AXIS);
141
142   return total.smobbed_copy ();
143
144 }
145
146 ADD_INTERFACE (Nested_system_start_delimiter,
147                "nested-system-start-delimiter-interface",
148                
149                "The brace, bracket or bar in front of the system.  By setting "
150                "@code{staff-hierarchy}, eg. to @code{(a (b d) c)}, nesting for staff "
151                "braces can be produced."  
152                ,
153                
154
155                /* properties */
156                "collapse-height "
157                "styles "
158                "staff-hierarchy "
159                );