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