]> git.donarmstrong.com Git - lilypond.git/blob - lily/accidental.cc
* VERSION (MY_PATCH_LEVEL): make 1.7.0
[lilypond.git] / lily / accidental.cc
1 #include "font-interface.hh"
2 #include "item.hh"
3 #include "molecule.hh"
4 #include "accidental-interface.hh"
5
6 /*
7   TODO: insert support for smaller cautionaries, tie-break-reminders.
8   Either here or in new-accidental-engraver.
9
10   'accidentals should go, for a single 'accidental property -- see
11   accidental-placement.cc
12
13 */
14
15
16 Molecule
17 parenthesize (Grob*me, Molecule m)
18 {
19   Molecule open = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-leftparen"));
20   Molecule close = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-rightparen"));
21   m.add_at_edge (X_AXIS, LEFT, Molecule (open), 0);
22   m.add_at_edge (X_AXIS, RIGHT, Molecule (close), 0);
23
24   return m;
25 }
26
27
28 MAKE_SCHEME_CALLBACK (Accidental_interface,after_line_breaking,1);
29 SCM
30 Accidental_interface::after_line_breaking (SCM smob)
31 {
32   Grob *me  = unsmob_grob (smob);
33   Grob *tie = unsmob_grob (me->get_grob_property ("tie"));
34
35   if (tie && !tie->original_)
36     {
37       me->suicide ();
38     }
39   return SCM_UNSPECIFIED;
40 }
41
42 Array<Box>
43 Accidental_interface::accurate_boxes (Grob *a,Grob**common)
44 {
45   Box b;
46   b[X_AXIS] = a->extent (a, X_AXIS);
47   b[Y_AXIS] = a->extent (a, Y_AXIS);
48
49   Array<Box> boxes;
50   
51   bool parens = false;
52   if (to_boolean (a->get_grob_property ("cautionary")))
53     {
54       SCM cstyle = a->get_grob_property ("cautionary-style");
55       parens = gh_equal_p (cstyle, ly_symbol2scm ("parentheses"));
56
57     }
58
59   SCM accs = a->get_grob_property ("accidentals");
60   SCM scm_style = a->get_grob_property ("style");
61   if (!gh_symbol_p (scm_style)
62       && !parens
63       && scm_ilength (accs) == 1)
64     {
65       if (gh_scm2int (gh_car (accs)) == -1)
66         {
67           Box stem = b;
68           Box bulb = b;
69
70           /*
71             we could make the stem thinner, but that places the flats
72             really close.
73           */
74           stem[X_AXIS][RIGHT] *= .5;
75           bulb[Y_AXIS][UP] *= .35;
76
77           boxes.push (bulb);
78           boxes.push (stem);
79         }
80       /*
81         TODO: add support for natural, double flat.
82        */
83     }
84
85   if (!boxes.size())
86     boxes.push (b);
87
88   Offset o (a->relative_coordinate (common[X_AXIS],  X_AXIS),
89             a->relative_coordinate (common[Y_AXIS],  Y_AXIS));
90   for(int i = boxes.size(); i--;)
91     {
92       boxes[i].translate(o);
93     }
94   
95   return boxes;
96 }
97
98 /*
99  * Some styles do not provide all flavours of accidentals, e.g. there
100  * is currently no sharp accidental in vaticana style.  In these cases
101  * this function falls back to one of the other styles.
102  */
103 String
104 Accidental_interface::get_fontcharname(String style, int alteration)
105 {
106   if (style == "hufnagel")
107     switch (alteration)
108       {
109       case -2: return "-2";
110       case -1: return "hufnagel-1";
111       case 0: return "vaticana0";
112       case 1: return "mensural1";
113       case 2: return "2";
114       }
115   if (style == "medicaea")
116     switch (alteration)
117       {
118       case -2: return "-2";
119       case -1: return "medicaea-1";
120       case 0: return "vaticana0";
121       case 1: return "mensural1";
122       case 2: return "2";
123       }
124   if (style == "vaticana")
125     switch (alteration)
126       {
127       case -2: return "-2";
128       case -1: return "vaticana-1";
129       case 0: return "vaticana0";
130       case 1: return "mensural1";
131       case 2: return "2";
132       }
133   if (style == "mensural")
134     switch (alteration)
135       {
136       case -2: return "-2";
137       case -1: return "mensural-1";
138       case 0: return "vaticana0";
139       case 1: return "mensural1";
140       case 2: return "2";
141       }
142   if (style == "neo_mensural")
143     style = ""; // currently same as default
144   if (style == "default")
145     style = "";
146   return style + to_string (alteration);
147 }
148
149 MAKE_SCHEME_CALLBACK (Accidental_interface,brew_molecule,1);
150 SCM
151 Accidental_interface::brew_molecule (SCM smob)
152 {
153   Grob *me = unsmob_grob (smob);
154   bool smaller = false;
155   bool parens = false;
156
157   bool caut  = to_boolean (me->get_grob_property ("cautionary"));
158   if (caut)
159     {
160       SCM cstyle = me->get_grob_property ("cautionary-style");
161       parens = gh_equal_p (cstyle, ly_symbol2scm ("parentheses"));
162       smaller = gh_equal_p (cstyle, ly_symbol2scm ("smaller"));
163     }
164
165   SCM scm_style = me->get_grob_property ("style");
166   String style;
167   if (gh_symbol_p (scm_style))
168     {
169       style = ly_scm2string (scm_symbol_to_string (scm_style));
170     }
171   else
172     {
173       /*
174         preferably no name for the default style.
175       */
176       style = "";
177     }
178
179   Font_metric *fm = 0;
180   if (smaller)
181     {
182       SCM ac = Font_interface::font_alist_chain (me);
183       ac = gh_cons (gh_cons (gh_cons
184                              (ly_symbol2scm ("font-relative-size"),
185                               scm_int2num (-1)), SCM_EOL),
186                     ac);
187       fm = Font_interface::get_font (me, ac);
188     }
189   else
190     fm = Font_interface::get_default_font (me);
191
192   Molecule mol;
193   for (SCM s = me->get_grob_property ("accidentals");
194        gh_pair_p (s); s = gh_cdr (s))
195     {
196       int alteration = gh_scm2int (gh_car (s));
197       String font_char = get_fontcharname (style, alteration);
198       Molecule acc (fm->find_by_name ("accidentals-" + font_char));
199
200       if (acc.empty_b())
201         {
202           me->warning (_f ("accidental `%s' not found", font_char));
203         }
204       else
205         {
206           mol.add_at_edge (X_AXIS,  RIGHT, acc, 0.1);
207         }
208     }
209
210   if (parens)
211     mol = parenthesize (me, mol); 
212
213   return mol.smobbed_copy();
214 }
215
216
217
218 ADD_INTERFACE (Accidental_interface, "accidental-interface",
219               "a single accidental",
220                "cautionary cautionary-style style tie accidentals");