From: fred Date: Tue, 26 Mar 2002 23:25:08 +0000 (+0000) Subject: lilypond-1.3.74 X-Git-Tag: release/1.5.59~1459 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=0181ed1353b16c6e7617e70aba462b67c214805e;p=lilypond.git lilypond-1.3.74 --- diff --git a/lily/afm.cc b/lily/afm.cc index 9f1f8045f5..c86c1faafc 100644 --- a/lily/afm.cc +++ b/lily/afm.cc @@ -24,7 +24,16 @@ Adobe_font_metric::Adobe_font_metric (AFM_Font_info * fi) name_to_metric_dict_[c->name] = i; } } - + + +SCM +Adobe_font_metric::make_afm (AFM_Font_info *fi) +{ + Adobe_font_metric * fm = new Adobe_font_metric (fi); + + return fm->smobbed_self(); +} + AFM_CharMetricInfo const * Adobe_font_metric::find_ascii_metric (int a , bool warn) const @@ -74,7 +83,7 @@ Adobe_font_metric::get_char (int code, bool warn) const return Box (Interval (0,0),Interval(0,0)); } -Adobe_font_metric* +SCM read_afm_file (String nm) { FILE *f = fopen (nm.ch_C() , "r"); @@ -89,7 +98,7 @@ read_afm_file (String nm) } fclose (f); - return new Adobe_font_metric (fi); + return Adobe_font_metric::make_afm (fi); } diff --git a/lily/font-metric.cc b/lily/font-metric.cc index 4443aa6399..467f0f84cf 100644 --- a/lily/font-metric.cc +++ b/lily/font-metric.cc @@ -67,14 +67,11 @@ Scaled_font_metric::text_dimension (String t) const Font_metric::~Font_metric () { - unsmobify_self (); } Font_metric::Font_metric () { - self_scm_ = SCM_EOL; name_ = SCM_EOL; - smobify_self (); } Font_metric::Font_metric (Font_metric const &) @@ -94,6 +91,15 @@ Scaled_font_metric::Scaled_font_metric (Font_metric* m, int s) orig_l_ = m; } +SCM +Scaled_font_metric::make_scaled_font_metric (Font_metric*m, int s) +{ + Scaled_font_metric *sfm = new Scaled_font_metric (m,s); + sfm->name_ = m->name_; + + return sfm->smobbed_self (); +} + SCM Font_metric::description () const { @@ -110,15 +116,11 @@ Scaled_font_metric::description () const } -void -Font_metric::do_smobify_self () -{ -} SCM Font_metric::mark_smob (SCM s) { - Font_metric * m = SMOB_TO_TYPE(Font_metric, s); + Font_metric * m = (Font_metric*) SCM_CELL_WORD_1(s); return m->name_; } @@ -134,5 +136,5 @@ Font_metric::print_smob (SCM s, SCM port, scm_print_state * ) IMPLEMENT_UNSMOB (Font_metric, metrics); -IMPLEMENT_SMOBS (Font_metric); - +IMPLEMENT_SIMPLE_SMOBS (Font_metric); +IMPLEMENT_DEFAULT_EQUAL_P(Font_metric); diff --git a/lily/lyric-phrasing-engraver.cc b/lily/lyric-phrasing-engraver.cc new file mode 100644 index 0000000000..c17755f745 --- /dev/null +++ b/lily/lyric-phrasing-engraver.cc @@ -0,0 +1,374 @@ +/* + lyric-phrasing-engraver.cc -- implement Lyric_phrasing_engraver + + source file of the GNU LilyPond music typesetter + + (c) 2000 Glen Prideaux +*/ +#include + +#include "lyric-phrasing-engraver.hh" +#include "note-head.hh" +#include "translator-group.hh" +#include "side-position-interface.hh" + +String get_context_id(Translator_group * ancestor, const char * type); +String trim_suffix(String &id); + +ADD_THIS_TRANSLATOR (Lyric_phrasing_engraver); + + +Lyric_phrasing_engraver::Lyric_phrasing_engraver() +{ + voice_alist_ = SCM_EOL; +} + +Lyric_phrasing_engraver::~Lyric_phrasing_engraver() +{ + /* + No need to delete alist_; that's what Garbage collection is for. + */ +} + +Voice_alist_entry * +Lyric_phrasing_engraver::lookup_context_id(const String &context_id) +{ + SCM key = ly_str02scm(context_id.ch_C()); + if( ! gh_null_p(voice_alist_) ) { + SCM s = scm_assoc(key, voice_alist_); + if(! (gh_boolean_p(s) && !to_boolean(s))) { + /* match found */ + return unsmob_voice_entry(gh_cdr(s)); + } + } + SCM val = Voice_alist_entry::make_entry (); + voice_alist_ = scm_acons(key, val, voice_alist_); + return unsmob_voice_entry (val); +} + + +void +Lyric_phrasing_engraver::record_notehead(const String &context_id, Score_element * notehead) +{ + Voice_alist_entry * v = lookup_context_id(context_id); + v->set_notehead(notehead); + // voice_alist_ = + // scm_assoc_set_x(voice_alist_, ly_str02scm(context_id.ch_C()), smobify(v)); +} + +void +Lyric_phrasing_engraver::record_lyric(const String &context_id, Score_element * lyric) +{ + Voice_alist_entry * v = lookup_context_id(context_id); + v->add_lyric(lyric); + // voice_alist_ = + // scm_assoc_set_x(voice_alist_, ly_str02scm(context_id.ch_C()), smobify(v)); +} + + + + +void +Lyric_phrasing_engraver::acknowledge_element(Score_element_info i) +{ + SCM p = get_property("automaticPhrasing"); + if(!to_boolean(p)) + return; + + + Score_element *h = i.elem_l_; + + if (Note_head::has_interface(h)) { + /* caught a note head ... do something with it */ + /* ... but not if it's a grace note ... */ + bool grace= to_boolean (i.elem_l_->get_elt_property ("grace")); + SCM wg = get_property ("weAreGraceContext"); + bool wgb = to_boolean (wg); + if (grace != wgb) + return; + + /* what's its Voice context name? */ + String voice_context_id = get_context_id(i.origin_trans_l_->daddy_trans_l_, "Voice"); + record_notehead(voice_context_id, h); + return; + } + /* now try for a lyric */ + if (h->has_interface (ly_symbol2scm ("lyric-syllable-interface"))) { + + /* what's its LyricVoice context name? */ + String lyric_voice_context_id = + get_context_id(i.origin_trans_l_->daddy_trans_l_, "LyricVoice"); + record_lyric(trim_suffix(lyric_voice_context_id), h); + return; + } +} + + +String +get_context_id(Translator_group * ancestor, const char *type) +{ + while(ancestor != 0 && ancestor->type_str_ != type) { + ancestor = ancestor->daddy_trans_l_; + } + + if(ancestor != 0) { + return ancestor->id_str_; + } + + return ""; +} + +String +trim_suffix(String &id) +{ + int index = id.index_i('-'); + if(index >= 0) { + return id.left_str(index); + } + return id; +} + + +void Lyric_phrasing_engraver::process_acknowledged () +{ + /* iterate through entries in voice_alist_ + for each, call set_lyric_align(alignment). Issue a warning if this returns false. + */ + Voice_alist_entry *entry; + String punc; + if (punc.empty_b()) { + SCM sp = get_property("phrasingPunctuation"); + punc = gh_string_p(sp) ? ly_scm2string(sp) : ".,;?!"; + } + + for(unsigned v=0; v < gh_length(voice_alist_); v++) { + entry = unsmob_voice_entry(gh_cdr(gh_list_ref(voice_alist_, gh_int2scm(v)))); + if(! entry->set_lyric_align(punc.ch_C())) + warning (_ ("lyrics found without matching notehead ... aligning on self")); + } +} + + +void +Lyric_phrasing_engraver::do_pre_move_processing () +{ + Voice_alist_entry * entry; + for(unsigned v=0; v < gh_length(voice_alist_); v++) { + entry = unsmob_voice_entry(gh_cdr(gh_list_ref(voice_alist_, gh_int2scm(v)))); + entry->next_lyric(); + } +} + + + +/*=========================================================================================*/ + +/** Voice_alist_entry is a class to be smobbed and entered as data in the association list + member of the Lyric_phrasing_engraver class. +*/ + +Voice_alist_entry::Voice_alist_entry() +{ + first_in_phrase_b_=true; + clear(); +} + + + + +void +Voice_alist_entry::clear() +{ + notehead_l_=0; + lyric_list_.clear(); + longest_lyric_=-1; + shortest_lyric_=-1; +} + +void +Voice_alist_entry::set_first_in_phrase(bool f) +{ + first_in_phrase_b_ = f; +} + +void +Voice_alist_entry::set_notehead(Score_element * notehead) +{ + if(!notehead_l_) + /* there should only be a single notehead, so silently ignore any extras */ + notehead_l_=notehead; +} + +void +Voice_alist_entry::add_lyric(Score_element * lyric) +{ + int this_lyric = lyric_list_.size(); + lyric_list_.push(lyric); + /* record longest and shortest lyrics */ + if(longest_lyric_>-1) { + Real this_length = (lyric->extent(X_AXIS)).length(); + if(this_length > (lyric_list_[longest_lyric_]->extent(X_AXIS)).length()) + longest_lyric_ = this_lyric; + if(this_length < (lyric_list_[shortest_lyric_]->extent(X_AXIS)).length()) + shortest_lyric_ = this_lyric; + } + else + longest_lyric_ = shortest_lyric_ = this_lyric; +} + +bool +Voice_alist_entry::set_lyric_align(const char *punc) +{ + if(lyric_list_.size()<2) { + /* Only for multi-stanza songs ... if we've only a single lyric (or none at all) we + do nothing. + */ + clear(); + return true; + } + + Score_element * lyric; + alignment_i_ = appropriate_alignment(punc); + + for(int l = 0; l < lyric_list_.size(); l++) { + /** set the x alignment of each lyric + */ + lyric = lyric_list_[l]; + lyric->set_elt_property("self-alignment-X", gh_int2scm(alignment_i_)); + + // centre on notehead + + if(notehead_l_) { + /* set the parent of each lyric to the notehead, + set the offset callback of each lyric to centered_on_parent, + */ + lyric->set_parent(notehead_l_, X_AXIS); + lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS); + /* reference is on the right of the notehead; move it left half way */ + lyric->translate_axis (-(notehead_l_->extent(X_AXIS)).center(), X_AXIS); + } + else { + /* No matching notehead: just align to the first lyric, and + issue a warning about lyric without matching notehead + */ + if(l) { + lyric->set_parent(lyric_list_[0], X_AXIS); + lyric->add_offset_callback (Side_position::centered_on_parent, X_AXIS); + } + else + lyric->add_offset_callback (Side_position::aligned_on_self, X_AXIS); + } + + if(alignment_i_ != CENTER) { + // right or left align ... + /* If length of longest lyric < 2 * length of shortest lyric, + - centre longest lyric on notehead + Otherwise + - move so shortest lyric just reaches notehead centre + */ + // FIXME: do we really know the lyric extent here? Some font sizing comes later? + Real translate; + if((lyric_list_[longest_lyric_]->extent(X_AXIS)).length() < + (lyric_list_[shortest_lyric_]->extent(X_AXIS)).length() * 2 ) + translate = alignment_i_*(lyric_list_[longest_lyric_]->extent(X_AXIS)).length()/2; + else + translate = alignment_i_*(lyric_list_[shortest_lyric_]->extent(X_AXIS)).length(); + lyric->translate_axis (translate, X_AXIS); + } + } + + return (notehead_l_ != 0); +} + +/** determine what alignment we want. + Rules: if first_in_phrase_b_ is set, then alignment is LEFT. + otherwise if each syllable ends in punctuation, then alignment is RIGHT + otherwise alignment is centre. +*/ +int +Voice_alist_entry::appropriate_alignment(const char *punc) +{ + if(first_in_phrase_b_) + return LEFT; + + Score_element * lyric; + bool end_phrase = true; + /* use a property to determine what constitutes punctuation */ + + for(int l = 0; l < lyric_list_.size() && end_phrase; l++) { + lyric = lyric_list_[l]; + SCM lyric_scm = lyric->get_elt_property("text"); + String lyric_str = gh_string_p(lyric_scm)?ly_scm2string(lyric_scm):""; + char lastchar; + if(lyric_str.length_i()>1) { + lastchar = lyric_str[lyric_str.length_i()-2]; + /* We look at the second last character, because lily always appends a space. */ + /* If it doesn't end in punctuation then it ain't an end of phrase */ + if(! strchr(punc, lastchar)) { + /* Special case: trailing space. Here examine the previous character and reverse the + sense of the test (i.e. trailing space makes a break without punctuation, or + suppresses a break with punctuation). + This behaviour can be suppressed by including a space in the + phrasingPunctuation property, in which case trailing space always means + the same as punctuation. + + FIXME: The extra space throws alignment out a bit. + */ + if(lastchar == ' ') { + if(lyric_str.length_i()>2) { + lastchar = lyric_str[lyric_str.length_i()-3]; + if(strchr(punc, lastchar)) + end_phrase=false; + } + } + else + end_phrase=false; + } + } + } + if(end_phrase) + return RIGHT; + + return CENTER; +} + +bool +Voice_alist_entry::is_empty() +{ + return lyric_list_.size()==0; +} + +void +Voice_alist_entry::next_lyric() +{ + first_in_phrase_b_ = (alignment_i_ == RIGHT); + clear(); +} + +/* SMOB */ + +#include "ly-smobs.icc" + +SCM +Voice_alist_entry::mark_smob (SCM) +{ + return SCM_EOL; +} + +int +Voice_alist_entry::print_smob (SCM, SCM port, scm_print_state * ) +{ + scm_puts ("#", port); + return 1; +} + +IMPLEMENT_UNSMOB(Voice_alist_entry, voice_entry); +IMPLEMENT_SIMPLE_SMOBS(Voice_alist_entry); +IMPLEMENT_DEFAULT_EQUAL_P(Voice_alist_entry); + +SCM +Voice_alist_entry::make_entry () +{ + Voice_alist_entry *vi = new Voice_alist_entry; + return vi->smobbed_self (); +} diff --git a/lily/midi-def.cc b/lily/midi-def.cc index 1013399eac..f5cbd2a952 100644 --- a/lily/midi-def.cc +++ b/lily/midi-def.cc @@ -39,8 +39,8 @@ Midi_def::set_tempo (Moment one_beat_mom, int beats_per_minute_i) { Moment beats_per_second = Moment (beats_per_minute_i) / Moment (60); - Moment *m = new Moment (Moment(1)/Moment(beats_per_second * one_beat_mom)); - scope_p_->set ("whole-in-seconds", smobify (m)); + Moment m = Moment(1)/Moment(beats_per_second * one_beat_mom); + scope_p_->set ("whole-in-seconds", m.make_scm()); } diff --git a/lily/spacing-engraver.cc b/lily/spacing-engraver.cc index de4be78cb2..7578fa0073 100644 --- a/lily/spacing-engraver.cc +++ b/lily/spacing-engraver.cc @@ -138,8 +138,8 @@ Spacing_engraver::do_pre_move_processing () Paper_column * sc = dynamic_cast (unsmob_element (get_property ("currentMusicalColumn"))); - SCM sh = smobify (new Moment (shortest_playing)); - SCM st = smobify (new Moment (starter)); + SCM sh = shortest_playing.make_scm( ); + SCM st = starter.make_scm(); sc->set_elt_property ("shortest-playing-duration", sh); sc->set_elt_property ("shortest-starter-duration", st); diff --git a/lily/tfm.cc b/lily/tfm.cc index 982b357300..7b6f008527 100644 --- a/lily/tfm.cc +++ b/lily/tfm.cc @@ -57,6 +57,7 @@ Tex_font_metric::Tex_font_metric () { } + static Tex_font_char_metric dummy_static_char_metric; Tex_font_char_metric const * @@ -89,11 +90,19 @@ Tex_font_metric::str () const return outstr; } -void -Tex_font_metric::clear (int n) -{ - for (int i=0; i < n; i++) - ascii_to_metric_idx_.push (-1); -} + +SCM +Tex_font_metric::make_tfm (String fn) +{ + Tex_font_metric * tfm_p = new Tex_font_metric; + Tex_font_metric_reader reader (fn); + + tfm_p->info_ = reader.info_; + tfm_p->header_ = reader.header_; + tfm_p->char_metrics_ = reader.char_metrics_; + tfm_p->ascii_to_metric_idx_ = reader.ascii_to_metric_idx_; + + return tfm_p->smobbed_self (); +}