]> git.donarmstrong.com Git - lilypond.git/blob - lily/text-engraver.cc
release: 1.5.29
[lilypond.git] / lily / text-engraver.cc
1 /*   
2   text-engraver.cc --  implement Text_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10
11 #include "engraver.hh"
12 #include "side-position-interface.hh"
13 #include "item.hh"
14 #include "musical-request.hh"
15 #include "stem.hh"
16 #include "rhythmic-head.hh"
17
18
19 /**
20    typeset directions that are  plain text.
21  */
22 class Text_engraver : public Engraver
23 {
24   Link_array<Text_script_req> reqs_;
25   Link_array<Item> texts_;
26 public:
27   TRANSLATOR_DECLARATIONS(Text_engraver);
28 protected:
29   virtual bool try_music (Music* m);
30   virtual void stop_translation_timestep ();
31   virtual void start_translation_timestep ();
32   virtual void create_grobs ();
33   virtual void acknowledge_grob (Grob_info);
34 };
35
36 bool
37 Text_engraver::try_music (Music *m)
38 {
39   if (dynamic_cast<Text_script_req*> (m)
40       && m->get_mus_property ("text-type") != ly_symbol2scm ("dynamic"))
41     {
42       reqs_.push (dynamic_cast<Text_script_req*> (m));
43       return true;
44     }
45   return false;
46 }
47
48 void
49 Text_engraver::acknowledge_grob (Grob_info inf)
50 {
51   if (Rhythmic_head::has_interface (inf.grob_l_))
52     {
53       for (int i=0; i < texts_.size (); i++)
54         {
55           Grob*t = texts_[i];
56           Side_position_interface::add_support (t,inf.grob_l_);
57
58           /*
59             ugh.
60            */
61           if (Side_position_interface::get_axis (t) == X_AXIS
62               && !t->get_parent (Y_AXIS))
63             t->set_parent (inf.grob_l_, Y_AXIS);
64           else if (Side_position_interface::get_axis (t) == Y_AXIS
65               && !t->get_parent (X_AXIS))
66             t->set_parent (inf.grob_l_, X_AXIS);
67         }
68     }
69   
70   if (Stem::has_interface (inf.grob_l_))
71     {
72       for (int i=0; i < texts_.size (); i++)
73         {
74           Side_position_interface::add_support (texts_[i],inf.grob_l_);
75         }
76     }
77 }
78
79 void
80 Text_engraver::create_grobs ()
81 {
82   if (texts_.size ())
83     return;
84   for (int i=0; i < reqs_.size (); i++)
85     {
86       Text_script_req * r = reqs_[i];
87       
88       // URG: Text vs TextScript
89       String basic = "TextScript";
90
91       if (r->get_mus_property ("text-type") == ly_symbol2scm ("finger"))
92         {
93           basic = "Fingering";
94         }
95
96       Item *text = new Item (get_property (basic.ch_C ()));
97
98       /*
99         FIXME -> need to use basic props.
100        */
101       SCM axisprop = get_property ("scriptHorizontal");
102       
103       Axis ax = to_boolean (axisprop) ? X_AXIS : Y_AXIS;
104       Side_position_interface::set_axis (text, ax);
105
106 #if 0
107       if (r->style_str_ == "finger" && ax == Y_AXIS)
108         {
109           /*
110             nicely center the scripts.
111            */ 
112           text->add_offset_callback (Side_position_interface::aligned_on_self_proc, X_AXIS);
113           text->add_offset_callback (Side_position_interface::centered_on_parent_proc, X_AXIS);
114         }
115 #endif
116       
117
118       
119       /*
120         make sure they're in order by adding i to the priority field.
121         */
122       text->set_grob_property ("script-priority",
123                               gh_int2scm (200 + i));
124
125       if (r->get_direction ())
126         Side_position_interface::set_direction (text, r->get_direction ());
127       
128       text->set_grob_property ("text", r->get_mus_property ("text"));
129       
130       SCM nonempty = get_property ("textNonEmpty");
131       if (to_boolean (nonempty))
132         /*
133           empty text: signal that no rods should be applied.  
134          */
135         text->set_grob_property ("no-spacing-rods" , SCM_BOOL_F);
136                 
137       announce_grob (text, r);
138       texts_.push (text);
139     }
140 }
141
142 void
143 Text_engraver::stop_translation_timestep ()
144 {
145   for (int i=0; i < texts_.size (); i++)
146     {
147       Item *ti = texts_[i];
148       if (!to_boolean (get_property ("scriptHorizontal")))
149         Side_position_interface::add_staff_support (ti);
150       typeset_grob (ti);
151     }
152   texts_.clear ();
153 }
154
155 void
156 Text_engraver::start_translation_timestep ()
157 {
158   reqs_.clear ();
159 }
160
161
162 Text_engraver::Text_engraver(){}
163
164 ENTER_DESCRIPTION(Text_engraver,
165 /* descr */       "Create text-scripts",
166 /* creats*/       "TextScript",
167 /* acks  */       "rhythmic-head-interface stem-interface",
168 /* reads */       "scriptHorizontal textNonEmpty",
169 /* write */       "");