]> git.donarmstrong.com Git - lilypond.git/blob - lily/bracket.cc
Web-ja: update introduction
[lilypond.git] / lily / bracket.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Jan Nieuwenhuizen <janneke@gnu.org>
5   Han-Wen Nienhuys <hanwen@xs4all.nl>
6
7   LilyPond is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   LilyPond is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21  #include "bracket.hh"
22
23  #include "axis-group-interface.hh"
24  #include "directional-element-interface.hh"
25  #include "grob.hh"
26  #include "lookup.hh"
27  #include "output-def.hh"
28  #include "staff-symbol-referencer.hh"
29  #include "spanner.hh"
30  #include "item.hh"
31  #include "line-interface.hh"
32
33 /*
34   should move to lookup?
35
36   TODO: this will fail for very short (shorter than the flare)
37   brackets.
38 */
39 Stencil
40 Bracket::make_bracket (Grob *me, // for line properties.
41                        Axis protrusion_axis, Offset dz,
42                        Drul_array<Real> height, Interval gap,
43                        Drul_array<Real> flare, Drul_array<Real> shorten)
44 {
45   Drul_array<Offset> corners (Offset (0, 0), dz);
46
47   Real length = dz.length ();
48   Drul_array<Offset> gap_corners;
49
50   Axis bracket_axis = other_axis (protrusion_axis);
51
52   Drul_array<Offset> straight_corners = corners;
53
54   for (LEFT_and_RIGHT (d))
55     straight_corners[d] += -d * shorten[d] / length * dz;
56
57   if (!gap.is_empty ())
58     {
59       for (LEFT_and_RIGHT (d))
60         gap_corners[d] = (dz * 0.5) + gap[d] / length * dz;
61     }
62
63   Drul_array<Offset> flare_corners = straight_corners;
64   for (LEFT_and_RIGHT (d))
65     {
66       flare_corners[d][bracket_axis] = straight_corners[d][bracket_axis];
67       flare_corners[d][protrusion_axis] += height[d];
68       straight_corners[d][bracket_axis] += -d * flare[d];
69     }
70
71   Stencil m;
72   if (!gap.is_empty ())
73     for (LEFT_and_RIGHT (d))
74       m.add_stencil (Line_interface::line (me, straight_corners[d],
75                                            gap_corners[d]));
76   else
77     m.add_stencil (Line_interface::line (me, straight_corners[LEFT],
78                                          straight_corners[RIGHT]));
79
80   if (scm_is_number (me->get_property ("dash-fraction")))
81     me->set_property ("dash-fraction", scm_from_double (1.0));
82   for (LEFT_and_RIGHT (d))
83     m.add_stencil (Line_interface::line (me, straight_corners[d],
84                                          flare_corners[d]));
85   return m;
86 }
87
88 /*
89   Return an ungapped bracket along either the X- or Y-axis.
90 */
91 Stencil
92 Bracket::make_axis_constrained_bracket (Grob *me, Real length, Axis a,
93                                         Direction dir)
94 {
95   Drul_array<Real> edge_height = robust_scm2interval (me->get_property ("edge-height"),
96                                                       Interval (1.0, 1.0));
97   Drul_array<Real> flare = robust_scm2interval (me->get_property ("bracket-flare"),
98                                                 Interval (0, 0));
99   Drul_array<Real> shorten = robust_scm2interval (me->get_property ("shorten-pair"),
100                                                   Interval (0, 0));
101
102   // Make sure that it points in the correct direction:
103   scale_drul (&edge_height, Real (-dir));
104
105   Offset start;
106   start[a] = length;
107
108   Drul_array<bool> connect_to_other
109     = robust_scm2booldrul (me->get_property ("connect-to-neighbor"),
110                            Drul_array<bool> (false, false));
111
112   for (LEFT_and_RIGHT (d))
113     {
114       if (connect_to_other[d])
115         {
116           edge_height[d] = 0.0;
117           flare[d] = 0.0;
118           shorten[d] = 0.0;
119         }
120     }
121
122   return make_bracket (me, other_axis (a), start, edge_height,
123                        Interval (), flare, shorten);
124 }
125
126 /*
127   Return an axis-constrained, ungapped bracket which encloses a group of
128   grobs.  Used for analysis brackets (HorizontalBracket) and
129   figured bass (BassFigureBracket).
130 */
131 Stencil
132 Bracket::make_enclosing_bracket (Grob *me, Grob *refpoint,
133                                  vector<Grob *> grobs, Axis a,
134                                  Direction dir)
135 {
136   Grob *common = common_refpoint_of_array (grobs, refpoint, a);
137   Interval ext = Axis_group_interface::relative_group_extent (grobs, common, a);
138
139   if (ext.is_empty ())
140     {
141       me->programming_error ("Can't enclose empty extents with bracket");
142       return Stencil ();
143     }
144   else
145     {
146       Stencil b = make_axis_constrained_bracket (me, ext.length (), a, dir);
147       b.translate_axis (ext[LEFT] - refpoint->relative_coordinate (common, a), a);
148
149       return b;
150     }
151 }