]> git.donarmstrong.com Git - lilypond.git/blob - lily/lookup.cc
release: 1.1.64
[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 #include <math.h>
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
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
386   Real realmag = 1.0;
387   if (paper_l->scope_p_->elem_b ("magnification_" + style))
388     {
389       font_mag = (int)paper_l->get_var ("magnification_" + style);
390       realmag = pow (1.2, font_mag);
391     }
392
393   /*
394     UGH.
395   */
396   SCM l = gh_eval_str (("(style-to-cmr \"" + style + "\")").ch_C());
397   if (l != SCM_BOOL_F)
398     {
399       style = ly_scm2string (SCM_CDR(l)) +to_str  ((int)font_h);
400     }
401
402   Real w = 0;
403   Interval ydims (0,0);
404
405   Font_metric* afm_l = all_fonts_global_p->find_font (style);
406   DOUT << "\nChars: ";
407
408
409   int brace_count =0;
410   for (int i = 0; i < text.length_i (); i++) 
411     {
412       
413       if (text[i]=='\\') 
414         {
415           for (i++; (i < text.length_i ()) && isalpha(text[i]); i++)
416             ;
417           i--; // Compensate for the increment in the outer loop!
418         }
419       else
420         {
421           if (text[i] == '{')
422             brace_count ++;
423           else if (text[i] == '}')
424             brace_count --;
425           Character_metric *c = afm_l->get_char ((unsigned char)text[i],false);
426
427           w += c->dimensions()[X_AXIS].length ();
428           ydims.unite (c->dimensions()[Y_AXIS]);
429         }
430     }
431
432   if(brace_count)
433     {
434       warning (_f ("Non-matching braces in text `%s', adding braces.", text.ch_C()));
435
436       if (brace_count < 0)
437         {
438           text = to_str ('{', -brace_count) + text;
439         }
440       else 
441         {
442           text = text + to_str ('}', brace_count);
443         }
444     }
445
446   ydims *= realmag;
447   m.dim_.x () = Interval (0, w*realmag);
448   m.dim_.y () = ydims;
449
450   
451   Atom at  (gh_list (text_scm_sym,
452                      gh_str02scm (text.ch_C()),
453                      SCM_UNDEFINED));
454   at.font_ = ly_symbol (style);
455   at.magn_ = gh_int2scm (font_mag);
456   
457   m.add_atom (&at);
458   return m;
459 }
460   
461
462 Molecule
463 Lookup::time_signature (int num, int den, Paper_def *paper_l) const
464 {
465   String sty = "number";
466   Molecule n (text (sty, to_str (num), paper_l));
467   Molecule d (text (sty, to_str (den), paper_l));
468   n.align_to (X_AXIS, CENTER);
469   d.align_to (X_AXIS, CENTER);
470   Molecule m;
471   if (den)
472     {
473       m.add_at_edge (Y_AXIS, UP, n, 0.0);
474       m.add_at_edge (Y_AXIS, DOWN, d, 0.0);
475     }
476   else
477     {
478       m = n;
479       m.align_to (Y_AXIS, CENTER);
480     }
481   return m;
482 }
483
484 Molecule
485 Lookup::staff_brace (Real y, int staff_size) const
486 {
487   Molecule m;
488   /*
489   (define (pianobrace y staffht)
490     (let* ((step 1.0)
491            (minht (* 2 staffht))
492            (maxht (* 7 minht))
493            )
494       (string-append
495        (select-font (string-append "feta-braces" (number->string (inexact->exact staffht))) 0)
496        (char (max 0 (/  (- (min y (- maxht step)) minht) step))))
497       )
498     )
499   */
500
501   Real step  = 1.0;
502   int minht  = 2 * staff_size;
503   int maxht = 7 *  minht;
504   int idx = int (((maxht - step) <? y - minht) / step);
505   idx = idx >? 0;
506   
507   SCM f =  ly_symbol (String ("feta-braces" + to_str (staff_size)));
508   SCM e =gh_list (char_scm_sym, gh_int2scm (idx), SCM_UNDEFINED);
509   Atom at  (e);
510   at.font_ = f;
511   
512   m.dim_[Y_AXIS] = Interval (-y/2,y/2);
513   m.dim_[X_AXIS] = Interval (0,0);
514   m.add_atom (&at);
515   return m;
516 }
517
518 Molecule
519 Lookup::hairpin (Real width, Real height, Real thick, bool decresc, bool continued) const
520 {
521   Molecule m;   
522
523   String hairpin = String (decresc ? "de" : "") + "crescendo";
524   Atom at  (gh_list (ly_symbol (hairpin),
525                      gh_double2scm (thick),
526                      gh_double2scm (width),
527                      gh_double2scm (height),
528                      gh_double2scm (continued ? height/2 : 0.0),
529                      SCM_UNDEFINED));
530   m.dim_.x () = Interval (0, width);
531   m.dim_.y () = Interval (-2*height, 2*height);
532
533   m.add_atom (&at);
534   return m;
535 }
536
537 Molecule
538 Lookup::tuplet_bracket (Real dy , Real dx, Real thick, Real gap, Real interline_f, Direction dir) const
539 {
540   Molecule m;
541
542   Atom at  (gh_list(tuplet_scm_sym,
543                     gh_double2scm (interline_f),
544                     gh_double2scm (gap),
545                     gh_double2scm (dx),
546                     gh_double2scm (dy),
547                     gh_double2scm (thick),
548                     gh_int2scm (dir),
549                     SCM_UNDEFINED));
550   m.add_atom (&at);
551
552   return m;
553 }
554
555 /*
556   Make a smooth curve along the points 
557  */
558 Molecule
559 Lookup::slur (Array<Offset> controls, Real linethick) const
560 {
561   Offset  delta_off = controls[3]- controls[0];
562   Molecule m; 
563
564   SCM scontrols [8];
565   int indices[] = {5,6,7,4,1,2,3,0};
566
567   for (int i= 0; i < 8; i++)
568     scontrols[i] = offset2scm (controls[indices[i]]);
569
570
571   Atom at  (gh_list (ly_symbol ("bezier-sandwich"),
572                      ly_quote_scm (array_to_list (scontrols, 8)),
573                      gh_double2scm (linethick),
574                      SCM_UNDEFINED));
575
576   m.dim_[X_AXIS] = Interval (0, delta_off[X_AXIS]);
577   m.dim_[Y_AXIS] = Interval (0 <? delta_off[Y_AXIS], 0 >? delta_off[Y_AXIS]);
578   m.add_atom (&at);
579   return m;
580 }
581
582 Molecule
583 Lookup::staff_bracket (Real y) const
584 {
585   Molecule m; 
586   Atom at  ( gh_list (bracket_scm_sym,
587                       gh_double2scm (y),
588                       SCM_UNDEFINED));
589   m.add_atom (&at);                              
590   m.dim_[Y_AXIS] = Interval (-y/2,y/2);
591   m.dim_[X_AXIS] = Interval (0,4 PT);
592
593   m.translate_axis (- 4. / 3. * m.dim_[X_AXIS].length (), X_AXIS);
594   return m;
595 }
596
597 Molecule
598 Lookup::volta (Real h, Real w, Real thick, bool vert_start, bool vert_end) const
599 {
600   Molecule m; 
601
602   Atom at  (gh_list (volta_scm_sym,
603                      gh_double2scm (h),
604                      gh_double2scm (w),
605                      gh_double2scm (thick),
606                      gh_int2scm (vert_start),
607                      gh_int2scm (vert_end),
608                      SCM_UNDEFINED));
609
610   m.dim_[Y_AXIS] = Interval (- h/2, h/2);
611   m.dim_[X_AXIS] = Interval (0, w);
612
613   m.add_atom (&at);
614   return m;
615 }
616
617 Molecule
618 Lookup::accordion (SCM s, Real interline_f) const
619 {
620   Molecule m;
621   String sym = ly_scm2string(SCM_CAR(s));
622   String reg = ly_scm2string(SCM_CAR(SCM_CDR(s)));
623
624   if (sym == "Discant")
625     {
626       Molecule r = afm_find("scripts-accDiscant");
627       m.add_molecule(r);
628       if (reg.left_str(1) == "F")
629         {
630           Molecule d = afm_find("scripts-accDot");
631           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
632           m.add_molecule(d);
633           reg = reg.right_str(reg.length_i()-1);
634         }
635       int eflag = 0x00;
636       if (reg.left_str(3) == "EEE")
637         {
638           eflag = 0x07;
639           reg = reg.right_str(reg.length_i()-3);
640         }
641       else if (reg.left_str(2) == "EE")
642         {
643           eflag = 0x05;
644           reg = reg.right_str(reg.length_i()-2);
645         }
646       else if (reg.left_str(2) == "Eh")
647         {
648           eflag = 0x04;
649           reg = reg.right_str(reg.length_i()-2);
650         }
651       else if (reg.left_str(1) == "E")
652         {
653           eflag = 0x02;
654           reg = reg.right_str(reg.length_i()-1);
655         }
656       if (eflag & 0x02)
657         {
658           Molecule d = afm_find("scripts-accDot");
659           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
660           m.add_molecule(d);
661         }
662       if (eflag & 0x04)
663         {
664           Molecule d = afm_find("scripts-accDot");
665           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
666           d.translate_axis(0.8 * interline_f PT, X_AXIS);
667           m.add_molecule(d);
668         }
669       if (eflag & 0x01)
670         {
671           Molecule d = afm_find("scripts-accDot");
672           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
673           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
674           m.add_molecule(d);
675         }
676       if (reg.left_str(2) == "SS")
677         {
678           Molecule d = afm_find("scripts-accDot");
679           d.translate_axis(0.5 * interline_f PT, Y_AXIS);
680           d.translate_axis(0.4 * interline_f PT, X_AXIS);
681           m.add_molecule(d);
682           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
683           m.add_molecule(d);
684           reg = reg.right_str(reg.length_i()-2);
685         }
686       if (reg.left_str(1) == "S")
687         {
688           Molecule d = afm_find("scripts-accDot");
689           d.translate_axis(0.5 * interline_f PT, Y_AXIS);
690           m.add_molecule(d);
691           reg = reg.right_str(reg.length_i()-1);
692         }
693     }
694   else if (sym == "Freebase")
695     {
696       Molecule r = afm_find("scripts-accFreebase");
697       m.add_molecule(r);
698       if (reg.left_str(1) == "F")
699         {
700           Molecule d = afm_find("scripts-accDot");
701           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
702           m.add_molecule(d);
703           reg = reg.right_str(reg.length_i()-1);
704         }
705       if (reg == "E")
706         {
707           Molecule d = afm_find("scripts-accDot");
708           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
709           m.add_molecule(d);
710         }
711     }
712   else if (sym == "Bayanbase")
713     {
714       Molecule r = afm_find("scripts-accBayanbase");
715       m.add_molecule(r);
716       if (reg.left_str(1) == "T")
717         {
718           Molecule d = afm_find("scripts-accDot");
719           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
720           m.add_molecule(d);
721           reg = reg.right_str(reg.length_i()-1);
722         }
723       /* include 4' reed just for completeness. You don't want to use this. */
724       if (reg.left_str(1) == "F")
725         {
726           Molecule d = afm_find("scripts-accDot");
727           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
728           m.add_molecule(d);
729           reg = reg.right_str(reg.length_i()-1);
730         }
731       if (reg.left_str(2) == "EE")
732         {
733           Molecule d = afm_find("scripts-accDot");
734           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
735           d.translate_axis(0.4 * interline_f PT, X_AXIS);
736           m.add_molecule(d);
737           d.translate_axis(-0.8 * interline_f PT, X_AXIS);
738           m.add_molecule(d);
739           reg = reg.right_str(reg.length_i()-2);
740         }
741       if (reg.left_str(1) == "E")
742         {
743           Molecule d = afm_find("scripts-accDot");
744           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
745           m.add_molecule(d);
746           reg = reg.right_str(reg.length_i()-1);
747         }
748     }
749   else if (sym == "Stdbase")
750     {
751       Molecule r = afm_find("scripts-accStdbase");
752       m.add_molecule(r);
753       if (reg.left_str(1) == "T")
754         {
755           Molecule d = afm_find("scripts-accDot");
756           d.translate_axis(interline_f * 3.5 PT, Y_AXIS);
757           m.add_molecule(d);
758           reg = reg.right_str(reg.length_i()-1);
759         }
760       if (reg.left_str(1) == "F")
761         {
762           Molecule d = afm_find("scripts-accDot");
763           d.translate_axis(interline_f * 2.5 PT, Y_AXIS);
764           m.add_molecule(d);
765           reg = reg.right_str(reg.length_i()-1);
766         }
767       if (reg.left_str(1) == "M")
768         {
769           Molecule d = afm_find("scripts-accDot");
770           d.translate_axis(interline_f * 2 PT, Y_AXIS);
771           d.translate_axis(interline_f PT, X_AXIS);
772           m.add_molecule(d);
773           reg = reg.right_str(reg.length_i()-1);
774         }
775       if (reg.left_str(1) == "E")
776         {
777           Molecule d = afm_find("scripts-accDot");
778           d.translate_axis(interline_f * 1.5 PT, Y_AXIS);
779           m.add_molecule(d);
780           reg = reg.right_str(reg.length_i()-1);
781         }
782       if (reg.left_str(1) == "S")
783         {
784           Molecule d = afm_find("scripts-accDot");
785           d.translate_axis(interline_f * 0.5 PT, Y_AXIS);
786           m.add_molecule(d);
787           reg = reg.right_str(reg.length_i()-1);
788         }
789     }
790   /* ugh maybe try to use regular font for S.B. and B.B and only use one font
791      for the rectangle */
792   else if (sym == "SB")
793     {
794       Molecule r = afm_find("scripts-accSB");
795       m.add_molecule(r);
796     }
797   else if (sym == "BB")
798     {
799       Molecule r = afm_find("scripts-accBB");
800       m.add_molecule(r);
801     }
802   else if (sym == "OldEE")
803     {
804       Molecule r = afm_find("scripts-accOldEE");
805       m.add_molecule(r);
806     }
807   else if (sym == "OldEES")
808     {
809       Molecule r = afm_find("scripts-accOldEES");
810       m.add_molecule(r);
811     }
812   return m;  
813 }