X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmensural-ligature-engraver.cc;h=8252e5a5697b6db66550a7c7e008e25ce16d4847;hb=2be67678488b5829a52acdf36ab4278477375b6d;hp=58134b68712d9c0a8fe9c2ccfbf4cdeb63708d7c;hpb=7aabfb20c46e0a1de41698ddc6859ccd3a6dea85;p=lilypond.git diff --git a/lily/mensural-ligature-engraver.cc b/lily/mensural-ligature-engraver.cc index 58134b6871..8252e5a569 100644 --- a/lily/mensural-ligature-engraver.cc +++ b/lily/mensural-ligature-engraver.cc @@ -3,11 +3,11 @@ source file of the GNU LilyPond music typesetter - (c) 2002--2003 Juergen Reuter + (c) 2002--2004 Juergen Reuter */ #include "mensural-ligature.hh" -#include "ligature-engraver.hh" +#include "coherent-ligature-engraver.hh" #include "event.hh" #include "warn.hh" #include "item.hh" @@ -18,23 +18,10 @@ #include "rhythmic-head.hh" #include "note-head.hh" #include "staff-symbol-referencer.hh" -#include "paper-def.hh" +#include "output-def.hh" #include "font-interface.hh" /* - * TODO: local accidentals: collect accidentals that occur within a - * ligature and put them before the ligature. If an accidental - * changes within a ligature, print a warning (user error) and ignore - * any further accidental for that pitch within that ligature - * (actually, in such a case, the user should split the ligature into - * two separate ligatures). Similarly, any object that, in ordinary - * notation, may be put to the left or to the right of a - * note-head/ligature-head, should be collected and put before or - * after the ligature. - * - * TODO: make spacing more robust: do not screw up spacing if user - * erroneously puts rest in ligature. - * * TODO: My resources on Franco of Cologne's rules claim that his * rules map ligature<->mensural timing in a non-ambigous way, but in * fact, as presented in these resources, the rules become ambigous as @@ -54,40 +41,20 @@ * * TODO: prohibit multiple voices within a ligature. * - * TODO: for each ligature, add Rod that represents the total length - * of the ligature (to preemptively avoid collision with adjacent - * notes); or maybe just additionally create a mensural-ligature grob - * (via Mensural_ligature::brew_molecule(SCM)) that just consists of a - * bounding box around all primitives of the ligature. - * * TODO: enhance robustness: in case of an illegal ligature (e.g. the * user events for a ligature that contains a minima or STATE_ERROR * is reached), automatically break the ligature into smaller, valid * pieces. - * - * TODO: In the future, there will be further ligature engravers - * implemented, such as a Vaticana_ligature_engraver. There will be - * redundant code between these engravers and the - * Mensural_ligature_engraver. In particular these are functions - * set_column_, fold_up_primitives, join_primitives, and - * ackowledge_grob; further the code for handling accidentals. It is - * not appropriate to put these things into Ligature_engraver, since, - * for example, Ligature_bracket_engraver does not share any of this - * code. Hence, we might to introduce a further subclass of - * Ligature_engraver which serves as super class for - * Mensural_ligature_engraver, Vaticana_ligature_engraver, among - * others. */ -class Mensural_ligature_engraver : public Ligature_engraver +class Mensural_ligature_engraver : public Coherent_ligature_engraver { protected: virtual Spanner *create_ligature_spanner (); - virtual void typeset_ligature (Spanner *ligature, - Array primitives); + virtual void build_ligature (Spanner *ligature, Array primitives); public: - TRANSLATOR_DECLARATIONS(Mensural_ligature_engraver); + TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver); private: int apply_transition (Array primitives, @@ -96,7 +63,6 @@ private: void propagate_properties (Spanner *ligature, Array primitives); void fold_up_primitives (Array primitives); void join_primitives (Array primitives); - void get_set_column (Item *item, Paper_column *new_col); }; @@ -107,44 +73,7 @@ Mensural_ligature_engraver::Mensural_ligature_engraver () Spanner * Mensural_ligature_engraver::create_ligature_spanner () { - return new Spanner (get_property ("MensuralLigature")); -} - -/* - * TODO: move this function to class Item? - */ -void -Mensural_ligature_engraver::get_set_column (Item *item, Paper_column *column) -{ - Item *parent = dynamic_cast (item->get_parent (X_AXIS)); - if (!parent) - { - programming_error ("failed tweaking paper column in ligature"); - return; - } - - String name = parent->name (); - if (!String::compare (name, "PaperColumn")) - { - // Change column not only for targeted item (NoteColumn), but - // also for all associated grobs (NoteSpacing, SeparationItem). - Grob *sl = Staff_symbol_referencer::get_staff_symbol (item); - for (SCM tail = parent->get_grob_property ("elements"); - gh_pair_p (tail); - tail = ly_cdr (tail)) - { - Item *sibling = unsmob_item (ly_car (tail)); - if ((sibling) && - (Staff_symbol_referencer::get_staff_symbol (sibling) == sl)) - { - sibling->set_parent (column, X_AXIS); - } - } - } - else - { - get_set_column (parent, column); - } + return make_spanner ("MensuralLigature", SCM_EOL); } /* @@ -282,7 +211,7 @@ Mensural_ligature_engraver::apply_transition (Array primitives, programming_error ("last_primitive undefined"); break; } - last_primitive->set_grob_property ("primitive", gh_int2scm (output)); + last_primitive->set_property ("primitive", scm_int2num (output)); break; case MLP_BB: case MLP_LB: @@ -297,8 +226,8 @@ Mensural_ligature_engraver::apply_transition (Array primitives, programming_error ("primitive undefined"); break; } - last_primitive->set_grob_property ("primitive", gh_int2scm (output)); - primitive->set_grob_property ("primitive", gh_int2scm (MLP_NONE)); + last_primitive->set_property ("primitive", scm_int2num (output)); + primitive->set_property ("primitive", scm_int2num (MLP_NONE)); break; case MLP_SS: // delayed primitive with two note heads @@ -312,8 +241,8 @@ Mensural_ligature_engraver::apply_transition (Array primitives, programming_error ("last_primitive undefined"); break; } - last_last_primitive->set_grob_property ("primitive", gh_int2scm (output)); - last_primitive->set_grob_property ("primitive", gh_int2scm (MLP_NONE)); + last_last_primitive->set_property ("primitive", scm_int2num (output)); + last_primitive->set_property ("primitive", scm_int2num (MLP_NONE)); break; default: programming_error (_f ("unexpected case fall-through")); @@ -355,7 +284,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) } else { - pitch = *unsmob_pitch (nr->get_mus_property ("pitch")); + pitch = *unsmob_pitch (nr->get_property ("pitch")); have_pitch = 1; } @@ -396,43 +325,31 @@ Mensural_ligature_engraver::transform_heads (Array primitives) // TODO: if (state == STATE_ERROR) { ... } } -void set_delta_pitch (Item *primitive, Grob_info info1, Grob_info info2) -{ - Pitch pitch1 = *unsmob_pitch (info1.music_cause ()->get_mus_property ("pitch")); - Pitch pitch2 = *unsmob_pitch (info2.music_cause ()->get_mus_property ("pitch")); - int delta_pitch = (pitch2.steps () - pitch1.steps ()); - primitive->set_grob_property ("delta-pitch", gh_int2scm (delta_pitch)); -} - /* - * A MensuralLigature grob consists of a bunch of LigatureHead grobs - * that are glued together. It (a) does not make sense to change + * A MensuralLigature grob consists of a bunch of NoteHead grobs that + * are glued together. It (a) does not make sense to change * properties like thickness or flexa-width from one head to the next * within a ligature (this would totally screw up alignment), and (b) * some of these properties (like flexa-width) are specific to * e.g. the MensuralLigature (as in contrast to e.g. LigatureBracket), - * and therefore should not be handled in the generic LigatureHead - * (which is also used by LigatureBracket). Therefore, we let the - * user control these properties via the concrete Ligature grob (like + * and therefore should not be handled in the NoteHead code (which is + * also used by LigatureBracket). Therefore, we let the user control + * these properties via the concrete Ligature grob (like * MensuralLigature) and then copy these properties as necessary to - * each of the LigatureHead grobs. This is what - * propagate_properties() does. + * each of the NoteHead grobs. This is what + * propagate_properties () does. */ void Mensural_ligature_engraver::propagate_properties (Spanner *ligature, Array primitives) { - SCM thickness_scm = ligature->get_grob_property ("thickness"); - Real thickness = (thickness_scm != SCM_EOL) ? - gh_scm2double (thickness_scm) : 1.4; - thickness *= ligature->get_paper ()->get_var ("linethickness"); + Real thickness = robust_scm2double (ligature->get_property ("thickness"), 1.4); + thickness *= ligature->get_paper ()->get_dimension (ly_symbol2scm ("linethickness")); Real head_width = Font_interface::get_default_font (ligature)-> find_by_name ("noteheads--1mensural").extent (X_AXIS).length (); - SCM flexa_width_scm = ligature->get_grob_property ("flexa-width"); - Real flexa_width = (flexa_width_scm != SCM_EOL) ? - gh_scm2double (flexa_width_scm) : 2.0; + Real flexa_width = robust_scm2double (ligature->get_property ("flexa-width"), 2); flexa_width *= Staff_symbol_referencer::staff_space (ligature); Real half_flexa_width = 0.5 * (flexa_width + thickness); @@ -440,29 +357,27 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature, for (int i = 0; i < primitives.size (); i++) { Item *primitive = dynamic_cast (primitives[i].grob_); - int output = gh_scm2int (primitive->get_grob_property ("primitive")); - primitive->set_grob_property ("thickness", - gh_double2scm (thickness)); + int output = ly_scm2int (primitive->get_property ("primitive")); + primitive->set_property ("thickness", + scm_make_real (thickness)); switch (output) { case MLP_NONE: - primitive->set_grob_property ("head-width", - gh_double2scm (half_flexa_width)); + primitive->set_property ("head-width", + scm_make_real (half_flexa_width)); break; case MLP_sc: case MLP_ss: case MLP_cs: - primitive->set_grob_property ("head-width", - gh_double2scm (head_width)); + primitive->set_property ("head-width", + scm_make_real (head_width)); break; case MLP_BB: case MLP_LB: case MLP_SS: - primitive->set_grob_property ("head-width", - gh_double2scm (half_flexa_width)); - primitive->set_grob_property ("flexa-width", - gh_double2scm (flexa_width)); - set_delta_pitch (primitive, - primitives[i], primitives[i+1]); + primitive->set_property ("head-width", + scm_make_real (half_flexa_width)); + primitive->set_property ("flexa-width", + scm_make_real (flexa_width)); break; default: programming_error (_f ("unexpected case fall-through")); @@ -488,19 +403,12 @@ Mensural_ligature_engraver::fold_up_primitives (Array primitives) if (i > 0) { -#if 0 - Rod r; - r.distance_ = distance; - r.item_l_drul_[LEFT] = first; - r.item_l_drul_[RIGHT] = current; - r.add_to_cols (); -#endif current->translate_axis (distance, X_AXIS); } distance += - gh_scm2double (current->get_grob_property ("head-width")) - - gh_scm2double (current->get_grob_property ("thickness")); + ly_scm2double (current->get_property ("head-width")) - + ly_scm2double (current->get_property ("thickness")); } } @@ -511,16 +419,16 @@ Mensural_ligature_engraver::join_primitives (Array primitives) for (int i = 0; i < primitives.size (); i++) { Grob_info info = primitives[i]; - Pitch pitch = *unsmob_pitch (info.music_cause ()->get_mus_property ("pitch")); + Pitch pitch = *unsmob_pitch (info.music_cause ()->get_property ("pitch")); if (i > 0) { Item *primitive = dynamic_cast (info.grob_); - int output = gh_scm2int (primitive->get_grob_property ("primitive")); + int output = ly_scm2int (primitive->get_property ("primitive")); if (output & MLP_ANY) { int delta_pitch = (pitch.steps () - last_pitch.steps ()); - primitive->set_grob_property ("join-left", - gh_int2scm (delta_pitch)); + primitive->set_property ("join-left-amount", + scm_int2num (delta_pitch)); } } last_pitch = pitch; @@ -528,24 +436,19 @@ Mensural_ligature_engraver::join_primitives (Array primitives) } void -Mensural_ligature_engraver::typeset_ligature (Spanner *ligature, - Array primitives) +Mensural_ligature_engraver::build_ligature (Spanner *ligature, + Array primitives) { transform_heads (primitives); propagate_properties (ligature, primitives); fold_up_primitives (primitives); join_primitives (primitives); - - for (int i = 0; i < primitives.size (); i++) - { - typeset_grob (primitives[i].grob_); - } } ENTER_DESCRIPTION (Mensural_ligature_engraver, /* descr */ "Handles Mensural_ligature_events by glueing special ligature heads together.", /* creats*/ "MensuralLigature", -/* accepts */ "ligature-event abort-event", -/* acks */ "ligature-head-interface note-head-interface rest-interface", +/* accepts */ "ligature-event", +/* acks */ "note-head-interface rest-interface", /* reads */ "", /* write */ "");