Workaround for broken MusicXML files (percussion clef in MuseScore)
[lilypond.git] / lily / break-align-engraver.cc
blob922978f2b1ca458c2a5ec6e29b09930c1997f01b
1 /*
2 break-align-engraver.cc -- implement Break_align_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8 #include "engraver.hh"
9 #include "protected-scm.hh"
10 #include "break-align-interface.hh"
11 #include "align-interface.hh"
12 #include "axis-group-interface.hh"
13 #include "context.hh"
14 #include "translator-group.hh"
15 #include "item.hh"
17 #include "translator.icc"
19 class Break_align_engraver : public Engraver
21 Item *align_;
22 SCM column_alist_;
23 Item *left_edge_;
25 void add_to_group (SCM, Item *);
26 void create_alignment (Grob_info);
27 protected:
28 void stop_translation_timestep ();
29 virtual void derived_mark () const;
30 public:
31 TRANSLATOR_DECLARATIONS (Break_align_engraver);
32 DECLARE_ACKNOWLEDGER (break_aligned);
33 DECLARE_ACKNOWLEDGER (break_alignable);
36 void
37 Break_align_engraver::stop_translation_timestep ()
39 column_alist_ = SCM_EOL;
41 align_ = 0;
42 left_edge_ = 0;
45 Break_align_engraver::Break_align_engraver ()
47 column_alist_ = SCM_EOL;
48 left_edge_ = 0;
49 align_ = 0;
52 void
53 Break_align_engraver::derived_mark () const
55 scm_gc_mark (column_alist_);
58 void
59 Break_align_engraver::acknowledge_break_alignable (Grob_info inf)
61 if (!align_)
62 create_alignment (inf);
64 Grob *g = inf.grob ();
66 if (!g->get_parent (X_AXIS))
67 g->set_parent (align_, X_AXIS);
70 void
71 Break_align_engraver::acknowledge_break_aligned (Grob_info inf)
73 if (Item *item = dynamic_cast<Item *> (inf.grob ()))
76 Removed check for item->empty (X_AXIS). --hwn 20/1/04
78 if (item->get_parent (X_AXIS))
79 return;
81 if (!Item::is_non_musical (item))
82 return;
84 SCM align_name = item->get_property ("break-align-symbol");
85 if (!scm_is_symbol (align_name))
86 return;
88 if (!align_)
89 create_alignment (inf);
91 add_to_group (align_name, item);
95 void
96 Break_align_engraver::create_alignment (Grob_info inf)
98 align_ = make_item ("BreakAlignment", SCM_EOL);
100 Context *origin = inf.origin_contexts (this)[0];
102 Translator_group *tg = origin->implementation ();
103 Engraver *random_source = dynamic_cast<Engraver *> (unsmob_translator (scm_car (tg->get_simple_trans_list ())));
104 if (!random_source)
105 random_source = this;
108 Make left edge appear to come from same context as clef/bar-line etc.
110 left_edge_ = random_source->make_item ("LeftEdge", SCM_EOL);
111 add_to_group (left_edge_->get_property ("break-align-symbol"),
112 left_edge_);
115 void
116 Break_align_engraver::add_to_group (SCM align_name, Item *item)
118 SCM s = scm_assoc (align_name, column_alist_);
119 Item *group = 0;
121 if (s != SCM_BOOL_F)
123 Grob *e = unsmob_grob (scm_cdr (s));
124 group = dynamic_cast<Item *> (e);
126 else
128 group = make_item ("BreakAlignGroup", item->self_scm ());
130 group->set_property ("break-align-symbol", align_name);
131 group->set_parent (align_, Y_AXIS);
133 column_alist_ = scm_assoc_set_x (column_alist_, align_name, group->self_scm ());
135 Break_alignment_interface::add_element (align_, group);
137 Axis_group_interface::add_element (group, item);
140 ADD_ACKNOWLEDGER (Break_align_engraver, break_aligned);
141 ADD_ACKNOWLEDGER (Break_align_engraver, break_alignable);
142 ADD_TRANSLATOR (Break_align_engraver,
143 /* doc */
144 "Align grobs with corresponding @code{break-align-symbols}"
145 " into groups, and order the groups according to"
146 " @code{breakAlignOrder}. The left edge of the alignment gets"
147 " a separate group, with a symbol @code{left-edge}.",
149 /* create */
150 "BreakAlignment "
151 "BreakAlignGroup "
152 "LeftEdge ",
154 /* read */
157 /* write */