]> git.donarmstrong.com Git - lilypond.git/blob - lily/lookup.cc
release: 1.1.59
[lilypond.git] / lily / lookup.cc
1 /*
2   lookup.cc -- implement simple Lookup methods.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8   Jan Nieuwenhuizen <janneke@gnu.org>
9
10   TODO
11       Glissando
12 */
13
14 #include <ctype.h>
15 #include "lookup.hh"
16 #include "debug.hh"
17 #include "dimensions.hh"
18 #include "scalar.hh"
19 #include "paper-def.hh"
20 #include "string-convert.hh"
21 #include "file-path.hh"
22 #include "main.hh"
23 #include "lily-guile.hh"
24 #include "all-fonts.hh"
25 #include "afm.hh"
26 #include "scope.hh"
27 #include "molecule.hh"
28 #include "atom.hh"
29 #include "lily-guile.hh"
30
31
32 Lookup::Lookup ()
33 {
34   afm_l_ = 0;  
35 }
36
37 Lookup::Lookup (Lookup const& s)
38 {
39   font_name_ = s.font_name_;
40   afm_l_ = 0;  
41 }
42
43
44 /*
45   build a ledger line for small pieces.
46  */
47 Molecule
48 Lookup::ledger_line (Interval xwid) const
49 {
50   Drul_array<Molecule> endings;
51   endings[LEFT] = afm_find ("noteheads-ledgerending");
52   Molecule * e = &endings[LEFT];
53   endings[RIGHT] = *e;
54   
55   Real thick = e->dim_[Y_AXIS].length();
56   Real len = e->dim_[X_AXIS].length () - thick;
57
58   Molecule total;
59   Direction d = LEFT;
60   do {
61     endings[d].translate_axis (xwid[d] - endings[d].dim_[X_AXIS][d], X_AXIS);
62     total.add_molecule (endings[d]);    
63   } while ((flip(&d)) != LEFT);
64
65   Real xpos = xwid [LEFT] + len;
66
67   while (xpos + len + thick /2 <= xwid[RIGHT])
68     {
69       e->translate_axis (len, X_AXIS);
70       total.add_molecule (*e);
71       xpos += len;
72     }
73
74   return total;
75 }
76
77
78 Molecule
79 Lookup::accidental (int j, bool cautionary) const
80 {
81   Molecule m(afm_find (String ("accidentals-") + to_str (j)));
82   if (cautionary) 
83     {
84       Molecule open = afm_find (String ("accidentals-("));
85       Molecule close = afm_find (String ("accidentals-)"));
86       m.add_at_edge(X_AXIS, LEFT, Molecule(open), 0);
87       m.add_at_edge(X_AXIS, RIGHT, Molecule(close), 0);
88     }
89   return m;
90 }
91
92
93
94 Molecule
95 Lookup::afm_find (String s, bool warn) const
96 {
97   if (!afm_l_)      
98     {
99       Lookup * me =     (Lookup*)(this);
100       me->afm_l_ = all_fonts_global_p->find_afm (font_name_);
101       if (!me->afm_l_)
102         {
103           warning (_f("Can't open `%s'\n", font_name_));
104           warning (_f("Search path %s\n", global_path.str ().ch_C()));
105           error (_f("Aborting"));
106         }
107     }
108   Adobe_font_char_metric cm = afm_l_->find_char (s, warn);
109   Molecule m;
110   if (cm.code () < 0)
111     {
112       /*
113         don't want people relying on this kind of dimension. 
114        */
115       m.set_empty (false);
116       return m;
117     }
118   
119   Atom at (gh_list (char_scm_sym,
120                     gh_int2scm (cm.code ()),
121                     SCM_UNDEFINED));
122   at.font_ = ly_symbol (font_name_.ch_C());
123   at.magn_ = gh_int2scm (0);
124   
125   m.dim_ = cm.dimensions();
126   m.add_atom (&at);
127   return m;
128 }
129
130 Molecule
131 Lookup::notehead (int j, String type) const
132 {
133   if (j > 2)
134     j = 2;
135
136   return afm_find (String ("noteheads-") + to_str (j) + type);
137 }
138
139 Molecule
140 Lookup::simple_bar (String type, Real h, Paper_def* paper_l) const
141 {
142   SCM thick = ly_symbol ("barthick_" + type);
143   Real w = 0.0;
144   
145   if (paper_l->scope_p_->elem_b (thick))
146     {
147       w = paper_l->get_realvar (thick);
148     }
149   else
150     {
151       programming_error ("No bar thickness set ! ");
152       w = 1 PT;
153     }
154   return filledbox (Box (Interval(0,w), Interval(-h/2, h/2)));
155 }
156
157   
158 Molecule
159 Lookup::bar (String str, Real h, Paper_def *paper_l) const
160 {
161   if (str == "bracket")
162     return staff_bracket (h);
163   else if (str == "brace")
164     {
165       Real staffht  = paper_l->get_var ("staffheight");
166       return staff_brace (h,staffht);
167     }
168   Real kern = paper_l->get_var ("bar_kern");
169   Real thinkern = paper_l->get_var ("bar_thinkern");
170
171   Molecule thin = simple_bar ("thin", h, paper_l);
172   Molecule thick = simple_bar ("thick", h, paper_l);
173   Molecule colon = afm_find ("dots-repeatcolon", paper_l);  
174
175   Molecule m;
176   
177   if (str == "")
178     {
179       return fill (Box (Interval(0, 0), Interval (-h/2, h/2)));
180     }
181   if (str == "scorepostbreak")
182     {
183       return simple_bar ("score", h, paper_l);
184     }
185   else if (str == "|")
186     {
187       return thin;
188     }
189   else if (str == "|.")
190     {
191       m.add_at_edge (X_AXIS, LEFT, thick, 0);      
192       m.add_at_edge (X_AXIS, LEFT, thin, kern);
193     }
194   else if (str == ".|")
195     {
196       m.add_at_edge (X_AXIS, RIGHT, thick, 0);
197       m.add_at_edge (X_AXIS, RIGHT, thin, kern);
198     }
199   else if (str == ":|")
200     {
201       m.add_at_edge (X_AXIS, LEFT, thick, 0);
202       m.add_at_edge (X_AXIS, LEFT, thin, kern);
203       m.add_at_edge (X_AXIS, LEFT, colon, kern);      
204     }
205   else if (str == "|:")
206     {
207       m.add_at_edge (X_AXIS, RIGHT, thick, 0);
208       m.add_at_edge (X_AXIS, RIGHT, thin, kern);
209       m.add_at_edge (X_AXIS, RIGHT, colon, kern);      
210     }
211   else if (str == ":|:")
212     {
213       m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
214       m.add_at_edge (X_AXIS, LEFT, colon, kern);      
215       m.add_at_edge (X_AXIS, RIGHT, thick, kern);
216       m.add_at_edge (X_AXIS, RIGHT, colon, kern);      
217     }
218   else if (str == ".|.")
219     {
220       m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
221       m.add_at_edge (X_AXIS, RIGHT, thick, kern);      
222     }
223   else if (str == "||")
224     {
225       m.add_at_edge (X_AXIS, RIGHT, thin, 0);
226       m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);      
227     }
228
229   return m;
230 }
231
232 Molecule 
233 Lookup::beam (Real slope, Real width, Real thick) const
234 {
235   Real height = slope * width; 
236   Real min_y = (0 <? height) - thick/2;
237   Real max_y = (0 >? height) + thick/2;
238
239   
240   Molecule m;
241   Atom at
242      (gh_list (beam_scm_sym,
243                                 gh_double2scm (width),
244                                 gh_double2scm (slope),
245                                 gh_double2scm (thick),
246                                 SCM_UNDEFINED));
247
248   m.dim_[X_AXIS] = Interval (0, width);
249   m.dim_[Y_AXIS] = Interval (min_y, max_y);
250   m.add_atom (&at);
251   return m;
252 }
253
254 Molecule
255 Lookup::clef (String st) const
256 {
257   return afm_find (String ("clefs-" + st));
258 }
259
260 SCM
261 offset2scm (Offset o)
262 {
263   return gh_list (gh_double2scm (o[X_AXIS]), gh_double2scm(o[Y_AXIS]),
264                   SCM_UNDEFINED);
265 }
266
267 Molecule
268 Lookup::dashed_slur (Array<Offset> controls, Real thick, Real dash) const
269 {
270   assert (controls.size () == 8);
271   Offset d = controls[3] - controls[0];
272   
273   Real dx = d[X_AXIS];
274   Real dy = d[Y_AXIS];
275
276   Molecule m;
277
278
279   m.dim_[X_AXIS] = Interval (0, dx);
280   m.dim_[Y_AXIS] = Interval (0 <? dy, 0 >? dy);
281
282   SCM sc[4];
283   for (int i=0; i<  4; i++)
284     {
285       sc[i] =  offset2scm (controls[i]);
286     }
287
288   Atom at
289     (gh_list (ly_symbol ("dashed-slur"),
290               gh_double2scm (thick), 
291               gh_double2scm (dash),
292               ly_quote_scm (array_to_list (sc, 4)),
293               SCM_UNDEFINED));
294   
295   
296   m.add_atom (&at);
297   return m;
298 }
299
300 Molecule
301 Lookup::dots () const
302 {
303   return afm_find (String ("dots-dot"));
304 }
305
306
307
308 Molecule
309 Lookup::fill (Box b) const
310 {
311   Molecule m;
312   m.dim_ = b;
313   return m;
314 }
315
316 Molecule
317 Lookup::rest (int j, bool o, String style) const
318 {
319   return afm_find (String ("rests-") + to_str (j) + (o ? "o" : "") + style);
320 }
321
322
323 Molecule
324 Lookup::special_time_signature (String s, int n, int d, Paper_def*pap) const
325 {
326   // First guess: s contains only the signature style
327   String symbolname = "timesig-" + s + to_str (n) + "/" + to_str (d);
328   
329   Molecule m = afm_find (symbolname, false);
330   if (!m.empty_b()) 
331     return m;
332
333   // Second guess: s contains the full signature name
334   m = afm_find ("timesig-"+s, false);
335   if (!m.empty_b ()) 
336     return m;
337
338   // Resort to default layout with numbers
339   return time_signature (n,d,pap);
340 }
341
342 Molecule
343 Lookup::filledbox (Box b ) const
344 {
345   Molecule m;
346   
347   Atom at  (gh_list (filledbox_scm_sym,
348                      gh_double2scm (-b[X_AXIS][LEFT]),
349                      gh_double2scm (b[X_AXIS][RIGHT]),                 
350                      gh_double2scm (-b[Y_AXIS][DOWN]),
351                      gh_double2scm (b[Y_AXIS][UP]),                    
352                      SCM_UNDEFINED));
353
354   m.dim_ = b;
355   m.add_atom (&at);
356   return m;
357 }
358
359
360
361 /**
362    Magnification steps.  These are powers of 1.2. The numbers are
363  taken from Knuth's plain.tex: */
364 static Real mag_steps[] = {1, 1, 1.200, 1.440, 1.7280,  2.074, 2.488};
365
366 /**
367    TODO: THIS IS UGLY.  Since the user has direct access to TeX
368    strings, we try some halfbaked attempt to detect TeX trickery.
369
370 */
371 Molecule
372 Lookup::text (String style, String text, Paper_def *paper_l) const
373 {
374   Molecule m;
375   if (style.empty_b ())
376     style = "roman";
377   
378   int font_mag = 0;
379   Real font_h = paper_l->get_var ("font_normal");
380   if (paper_l->scope_p_->elem_b ("font_" + style))
381     {
382       font_h = paper_l->get_var ("font_" + style);
383     }
384    
385   if (paper_l->scope_p_->elem_b ("magnification_" + style))
386     {
387       font_mag = (int)paper_l->get_var ("magnification_" + style);
388     }
389
390   /*
391     UGH.
392   */
393   SCM l = gh_eval_str (("(style-to-cmr \"" + style + "\")").ch_C());
394   if (l != SCM_BOOL_F)
395     {
396       style = ly_scm2string (SCM_CDR(l)) +to_str  ((int)font_h);
397     }
398
399   Real w = 0;
400   Interval ydims (0,0);
401
402   Font_metric* afm_l = all_fonts_global_p->find_font (style);
403   DOUT << "\nChars: ";
404
405
406   int brace_count =0;
407   for (int i = 0; i < text.length_i (); i++) 
408     {
409       
410       if (text[i]=='\\') 
411         {
412           for (i++; (i < text.length_i ()) && isalpha(text[i]); i++)
413             ;
414           i--; // Compensate for the increment in the outer loop!
415         }
416       else
417         {
418           if (text[i] == '{')
419             brace_count ++;
420           else if (text[i] == '}')
421             brace_count --;
422           Character_metric *c = afm_l->get_char ((unsigned char)text[i],false);
423
424           w += c->dimensions()[X_AXIS].length ();
425           ydims.unite (c->dimensions()[Y_AXIS]);
426         }
427     }
428
429   if (font_mag > 1 && font_mag < 7 )
430     {
431       /* UGH  */ 
432       w *= mag_steps[font_mag];
433       ydims *= mag_steps[font_mag];
434     }
435
436   if(brace_count)
437     {
438       warning (_f ("Non-matching braces in text `%s', adding braces.", text.ch_C()));
439
440       if (brace_count < 0)
441         {
442           text = to_str ('{', -brace_count) + text;
443         }
444       else 
445         {
446           text = text + to_str ('}', brace_count);
447         }
448     }
449
450   
451   DOUT << "\n" << to_str (w) << "\n";
452   m.dim_.x () = Interval (0, w);
453   m.dim_.y () = ydims;
454
455   
456   Atom at  (gh_list (text_scm_sym,
457                      gh_str02scm (text.ch_C()),
458                      SCM_UNDEFINED));
459   at.font_ = ly_symbol (style);
460   at.magn_ = gh_int2scm (font_mag);
461   
462   m.add_atom (&at);
463   return m;
464 }
465   
466
467 Molecule
468 Lookup::time_signature (int num, int den, Paper_def *paper_l) const
469 {
470   String sty = "number";
471   Molecule n (text (sty, to_str (num), paper_l));
472   Molecule d (text (sty, to_str (den), paper_l));
473   n.align_to (X_AXIS, CENTER);
474   d.align_to (X_AXIS, CENTER);
475   Molecule m;
476   if (den)
477     {
478       m.add_at_edge (Y_AXIS, UP, n, 0.0);
479       m.add_at_edge (Y_AXIS, DOWN, d, 0.0);
480     }
481   else
482     {
483       m = n;
484       m.align_to (Y_AXIS, CENTER);
485     }
486   return m;
487 }
488
489 Molecule
490 Lookup::staff_brace (Real y, int staff_size) const
491 {
492   Molecule m;
493   /*
494   (define (pianobrace y staffht)
495     (let* ((step 1.0)
496            (minht (* 2 staffht))
497            (maxht (* 7 minht))
498            )
499       (string-append
500        (select-font (string-append "feta-braces" (number->string (inexact->exact staffht))) 0)
501        (char (max 0 (/  (- (min y (- maxht step)) minht) step))))
502       )
503     )
504   */
505
506   
507   Atom at  (gh_list (pianobrace_scm_sym,
508                      gh_double2scm (y),
509                      gh_int2scm (staff_size),
510                      SCM_UNDEFINED
511                      ));
512   
513   m.dim_[Y_AXIS] = Interval (-y/2,y/2);
514   m.dim_[X_AXIS] = Interval (0,0);
515   m.add_atom (&at);
516   return m;
517 }
518
519 Molecule
520 Lookup::hairpin (Real width, Real height, Real thick, bool decresc, bool continued) const
521 {
522   Molecule m;   
523
524   String hairpin = String (decresc ? "de" : "") + "crescendo";
525   Atom at  (gh_list (ly_symbol (hairpin),
526                      gh_double2scm (thick),
527                      gh_double2scm (width),
528                      gh_double2scm (height),
529                      gh_double2scm (continued ? height/2 : 0.0),
530                      SCM_UNDEFINED));
531   m.dim_.x () = Interval (0, width);
532   m.dim_.y () = Interval (-2*height, 2*height);
533
534   m.add_atom (&at);
535   return m;
536 }
537
538 Molecule
539 Lookup::tuplet_bracket (Real dy , Real dx, Real thick, Real gap, Real interline_f, Direction dir) const
540 {
541   Molecule m;
542
543   Atom at  (gh_list(tuplet_scm_sym,
544                     gh_double2scm (interline_f),
545                     gh_double2scm (gap),
546                     gh_double2scm (dx),
547                     gh_double2scm (dy),
548                     gh_double2scm (thick),
549                     gh_int2scm (dir),
550                     SCM_UNDEFINED));
551   m.add_atom (&at);
552
553   return m;
554 }
555
556 /*
557   Make a smooth curve along the points 
558  */
559 Molecule
560 Lookup::slur (Array<Offset> controls, Real linethick) const
561 {
562   Offset  delta_off = controls[3]- controls[0];
563   Molecule m; 
564
565   SCM scontrols [8];
566   int indices[] = {5,6,7,4,1,2,3,0};
567
568   for (int i= 0; i < 8; i++)
569     scontrols[i] = offset2scm (controls[indices[i]]);
570
571
572   Atom at  (gh_list (ly_symbol ("bezier-sandwich"),
573                      ly_quote_scm (array_to_list (scontrols, 8)),
574                      gh_double2scm (linethick),
575                      SCM_UNDEFINED));
576
577   m.dim_[X_AXIS] = Interval (0, delta_off[X_AXIS]);
578   m.dim_[Y_AXIS] = Interval (0 <? delta_off[Y_AXIS], 0 >? delta_off[Y_AXIS]);
579   m.add_atom (&at);
580   return m;
581 }
582
583 Molecule
584 Lookup::staff_bracket (Real y) const
585 {
586   Molecule m; 
587   Atom at  ( gh_list (bracket_scm_sym,
588                       gh_double2scm (y),
589                       SCM_UNDEFINED));
590   m.add_atom (&at);                              
591   m.dim_[Y_AXIS] = Interval (-y/2,y/2);
592   m.dim_[X_AXIS] = Interval (0,4 PT);
593
594   m.translate_axis (- 4. / 3. * m.dim_[X_AXIS].length (), X_AXIS);
595   return m;
596 }
597
598 Molecule
599 Lookup::volta (Real h, Real w, Real thick, bool vert_start, bool vert_end) const
600 {
601   Molecule m; 
602
603   Atom at  (gh_list (volta_scm_sym,
604                      gh_double2scm (h),
605                      gh_double2scm (w),
606                      gh_double2scm (thick),
607                      gh_int2scm (vert_start),
608                      gh_int2scm (vert_end),
609                      SCM_UNDEFINED));
610
611   m.dim_[Y_AXIS] = Interval (- h/2, h/2);
612   m.dim_[X_AXIS] = Interval (0, w);
613
614   m.add_atom (&at);
615   return m;
616 }
617
618 Molecule
619 Lookup::accordion (SCM s, Real interline_f) const
620 {
621   Molecule m;
622   String sym = ly_scm2string(SCM_CAR(s));
623   String reg = ly_scm2string(SCM_CAR(SCM_CDR(s)));
624
625   if (sym == "Discant")
626     {
627       Molecule r = afm_find("scripts-accDiscant");
628       m.add_molecule(r);
629       if (reg.left_str(1) == "F")
630         {
631           Molecule d = afm_find("scripts-accDot");
632           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
633           m.add_molecule(d);
634           reg = reg.right_str(reg.length_i()-1);
635         }
636       int eflag = 0x00;
637       if (reg.left_str(3) == "EEE")
638         {
639           eflag = 0x07;
640           reg = reg.right_str(reg.length_i()-3);
641         }
642       else if (reg.left_str(2) == "EE")
643         {
644           eflag = 0x05;
645           reg = reg.right_str(reg.length_i()-2);
646         }
647       else if (reg.left_str(2) == "Eh")
648         {
649           eflag = 0x04;
650           reg = reg.right_str(reg.length_i()-2);
651         }
652       else if (reg.left_str(1) == "E")
653         {
654           eflag = 0x02;
655           reg = reg.right_str(reg.length_i()-1);
656         }
657       if (eflag & 0x02)
658         {
659           Molecule d = afm_find("scripts-accDot");
660           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
661           m.add_molecule(d);
662         }
663       if (eflag & 0x04)
664         {
665           Molecule d = afm_find("scripts-accDot");
666           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
667           d.translate_axis(0.8 * interline_f PT, X_AXIS);
668           m.add_molecule(d);
669         }
670       if (eflag & 0x01)
671         {
672           Molecule d = afm_find("scripts-accDot");
673           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
674           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
675           m.add_molecule(d);
676         }
677       if (reg.left_str(2) == "SS")
678         {
679           Molecule d = afm_find("scripts-accDot");
680           d.translate_axis(0.5 * interline_f PT, Y_AXIS);
681           d.translate_axis(0.4 * interline_f PT, X_AXIS);
682           m.add_molecule(d);
683           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
684           m.add_molecule(d);
685           reg = reg.right_str(reg.length_i()-2);
686         }
687       if (reg.left_str(1) == "S")
688         {
689           Molecule d = afm_find("scripts-accDot");
690           d.translate_axis(0.5 * interline_f PT, Y_AXIS);
691           m.add_molecule(d);
692           reg = reg.right_str(reg.length_i()-1);
693         }
694     }
695   else if (sym == "Freebase")
696     {
697       Molecule r = afm_find("scripts-accFreebase");
698       m.add_molecule(r);
699       if (reg.left_str(1) == "F")
700         {
701           Molecule d = afm_find("scripts-accDot");
702           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
703           m.add_molecule(d);
704           reg = reg.right_str(reg.length_i()-1);
705         }
706       if (reg == "E")
707         {
708           Molecule d = afm_find("scripts-accDot");
709           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
710           m.add_molecule(d);
711         }
712     }
713   else if (sym == "Bayanbase")
714     {
715       Molecule r = afm_find("scripts-accBayanbase");
716       m.add_molecule(r);
717       if (reg.left_str(1) == "T")
718         {
719           Molecule d = afm_find("scripts-accDot");
720           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
721           m.add_molecule(d);
722           reg = reg.right_str(reg.length_i()-1);
723         }
724       /* include 4' reed just for completeness. You don't want to use this. */
725       if (reg.left_str(1) == "F")
726         {
727           Molecule d = afm_find("scripts-accDot");
728           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
729           m.add_molecule(d);
730           reg = reg.right_str(reg.length_i()-1);
731         }
732       if (reg.left_str(2) == "EE")
733         {
734           Molecule d = afm_find("scripts-accDot");
735           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
736           d.translate_axis(0.4 * interline_f PT, X_AXIS);
737           m.add_molecule(d);
738           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
739           m.add_molecule(d);
740           reg = reg.right_str(reg.length_i()-2);
741         }
742       if (reg.left_str(1) == "E")
743         {
744           Molecule d = afm_find("scripts-accDot");
745           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
746           m.add_molecule(d);
747           reg = reg.right_str(reg.length_i()-1);
748         }
749     }
750   else if (sym == "Stdbase")
751     {
752       Molecule r = afm_find("scripts-accStdbase");
753       m.add_molecule(r);
754       if (reg.left_str(1) == "T")
755         {
756           Molecule d = afm_find("scripts-accDot");
757           d.translate_axis(interline_f * 3.5 PT, Y_AXIS);
758           m.add_molecule(d);
759           reg = reg.right_str(reg.length_i()-1);
760         }
761       if (reg.left_str(1) == "F")
762         {
763           Molecule d = afm_find("scripts-accDot");
764           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
765           m.add_molecule(d);
766           reg = reg.right_str(reg.length_i()-1);
767         }
768       if (reg.left_str(1) == "M")
769         {
770           Molecule d = afm_find("scripts-accDot");
771           d.translate_axis(interline_f * 2 PT, Y_AXIS);
772           d.translate_axis(interline_f PT, X_AXIS);
773           m.add_molecule(d);
774           reg = reg.right_str(reg.length_i()-1);
775         }
776       if (reg.left_str(1) == "E")
777         {
778           Molecule d = afm_find("scripts-accDot");
779           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
780           m.add_molecule(d);
781           reg = reg.right_str(reg.length_i()-1);
782         }
783       if (reg.left_str(1) == "S")
784         {
785           Molecule d = afm_find("scripts-accDot");
786           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
787           m.add_molecule(d);
788           reg = reg.right_str(reg.length_i()-1);
789         }
790     }
791   /* ugh maybe try to use regular font for S.B. and B.B and only use one font
792      for the rectangle */
793   else if (sym == "SB")
794     {
795       Molecule r = afm_find("scripts-accSB");
796       m.add_molecule(r);
797     }
798   else if (sym == "BB")
799     {
800       Molecule r = afm_find("scripts-accBB");
801       m.add_molecule(r);
802     }
803   else if (sym == "OldEE")
804     {
805       Molecule r = afm_find("scripts-accOldEE");
806       m.add_molecule(r);
807     }
808   else if (sym == "OldEES")
809     {
810       Molecule r = afm_find("scripts-accOldEES");
811       m.add_molecule(r);
812     }
813   return m;  
814 }