]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-1.3.101
authorfred <fred>
Mon, 30 Oct 2000 11:55:45 +0000 (11:55 +0000)
committerfred <fred>
Mon, 30 Oct 2000 11:55:45 +0000 (11:55 +0000)
lily/custos-engraver.cc [new file with mode: 0644]
lily/custos.cc [new file with mode: 0644]
lily/include/custos.hh [new file with mode: 0644]

diff --git a/lily/custos-engraver.cc b/lily/custos-engraver.cc
new file mode 100644 (file)
index 0000000..5f15194
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+  custos-engraver.cc -- implement Custos_engraver
+
+  source file of the GNU LilyPond music typesetter
+
+  (C) 2000 Juergen Reuter <reuterj@ira.uka.de>,
+
+  Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  
+*/
+
+#include "engraver.hh"
+#include "bar.hh"
+#include "item.hh"
+#include "note-head.hh"
+#include "staff-symbol-referencer.hh"
+#include "warn.hh"
+#include "musical-request.hh"
+
+/*
+  This class implements an engraver for custos symbols.
+*/
+class Custos_engraver : public Engraver
+{
+public:
+  Custos_engraver();
+  virtual void do_post_move_processing();
+  virtual void acknowledge_element(Score_element_info);
+  virtual void do_process_music ();
+  virtual void process_acknowledged ();
+  virtual void do_pre_move_processing ();
+  virtual void do_removal_processing ();
+  VIRTUAL_COPY_CONS(Translator);
+
+private:
+  Item * create_custos();
+  bool custos_permitted;
+  Link_array<Score_element> custos_arr_;
+  Array<Musical_pitch> pitches_;
+};
+
+Custos_engraver::Custos_engraver ()
+{
+  custos_permitted = false;
+}
+
+
+void
+Custos_engraver::do_pre_move_processing()
+{
+  /*
+    delay typeset until we're at the next moment, so we can silence custodes at the end of the piece.
+   */
+}
+
+void
+Custos_engraver::do_post_move_processing ()
+{
+  for (int i = custos_arr_.size (); i--;)
+    {
+      typeset_element (custos_arr_[i]);
+    }
+  custos_arr_.clear ();
+  pitches_.clear ();
+
+  custos_permitted = false;
+}
+
+
+/*
+  TODO check if this works with forced bar lines?
+ */
+void
+Custos_engraver::do_process_music ()
+{
+  if (gh_string_p (get_property( "whichBar")))
+    custos_permitted = true;
+}
+
+void
+Custos_engraver::acknowledge_element (Score_element_info info)
+{
+  Item *item = dynamic_cast <Item *>(info.elem_l_);
+  if (item)
+    {
+      if (Bar::has_interface (info.elem_l_))
+       custos_permitted = true;
+      else if (Note_head::has_interface (info.elem_l_))
+       {
+
+         /*
+           ideally, we'd do custos->set_parent (Y_AXIS, notehead),
+           but since the note head lives on the other system, we can't
+
+           So we copy the position from the note head pitch.  We
+           don't look at the staff-position, since we can't be sure
+           whether Clef_engraver already applied a vertical shift.
+         */
+         
+         pitches_.push (dynamic_cast<Note_req*> (info.req_l_)->pitch_);
+       }
+    }
+}
+
+void
+Custos_engraver::process_acknowledged ()
+{
+  if (custos_permitted)
+    {
+      for (int i = pitches_.size (); i--;)
+       {
+         Item *c = create_custos ();
+         
+         c->set_elt_property ("staff-position",
+                              gh_int2scm (pitches_[i].steps ()));
+         
+       }
+
+      pitches_.clear ();
+    }
+}
+
+Item* 
+Custos_engraver::create_custos()
+{
+  SCM basicProperties = get_property ("Custos");
+  Item* custos = new Item (basicProperties);
+  
+  announce_element (custos, 0);
+  custos_arr_.push (custos);
+  
+  return custos;
+}
+
+void
+Custos_engraver::do_removal_processing ()
+{
+  for (int i = custos_arr_.size (); i--;)
+    {
+      custos_arr_[i]->suicide ();
+      typeset_element (custos_arr_[i]);
+    }
+  custos_arr_.clear ();
+}
+
+ADD_THIS_TRANSLATOR (Custos_engraver);
+
diff --git a/lily/custos.cc b/lily/custos.cc
new file mode 100644 (file)
index 0000000..24091d6
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+  custos.cc -- implement Custos
+
+  source file of the GNU LilyPond music typesetter
+
+  (C) 2000 Juergen Reuter <reuterj@ira.uka.de>
+*/
+
+/* TODO:
+
+ - merge create_ledger_line () and Note_head::create_ledger_line()
+
+ - rewrite create_ledger_line() to support short and thin ledger lines
+
+ - do not show if a clef change immediately follows in the next line
+
+ - make custos direction control configurable
+
+ - decide: do or do not print custos if the next line starts with a rest
+
+*/
+
+
+#include <stdio.h>
+#include "staff-symbol-referencer.hh"
+#include "custos.hh"
+#include "molecule.hh"
+#include "lookup.hh"
+#include "debug.hh"
+#include "note-head.hh"
+#include "item.hh"
+#include "font-interface.hh"
+
+/*
+   This function is a patched and hopefully much more understandable
+   rewrite of Note_head::ledger_line().  It still has some
+   bugs/limitations:
+ *
+   (1) The term thick/2 probably should be thick*2 (probably a bug,
+   see the code below).
+ *
+   (2) The minimal width of the resulting ledger line equals the width
+   of the noteheads-ledgerending symbol (a limitation):
+ *
+     (---- left ledger ending
+     ----) right ledger ending
+     (---) resulting ledger line (just ok)
+ *
+   If x_extent ("xwid" in Note_head) is less than the width of the
+   ledger ending, the width of the total ledger line is even *greater*
+   than the width of a ledger ending (I would call this a bug).  In
+   the below code, the condition "if (x_extent.length() >
+   slice_x_extent.length())" avoids outputting the left ending in such
+   cases (rather a silly workaround, but better than nothing).
+ *
+       (---- left ledger ending
+     ----)   right ledger ending
+       (-)   desired ledger line
+     ------- resulting ledger line (too long)
+     ----)   resulting ledger line with additional "if" (still too long)
+ *
+   The algorithm works properly only for a desired ledger line width
+   greater than the width of the ledger ending:
+ *
+     (----    left ledger ending
+        ----) right ledger ending
+     (------) desired ledger line
+     (------) resulting ledger line (ok)
+ *
+ * (3) The thickness of the ledger line is fixed (limitation).
+ */
+Molecule create_ledger_line (Interval x_extent, Score_element *me) 
+{
+  Molecule line;
+  Molecule slice = Font_interface::get_default_font (me)->find_by_name ("noteheads-ledgerending");
+  Interval slice_x_extent = slice.extent(X_AXIS);
+  Interval slice_y_extent = slice.extent(Y_AXIS);
+
+  // Create left ending of ledger line.
+  Molecule left_ending = slice;
+  left_ending.translate_axis (x_extent[LEFT] - slice_x_extent[LEFT], X_AXIS);
+  if (x_extent.length() > slice_x_extent.length())
+    line.add_molecule (left_ending);
+
+  // Create right ending of ledger line.
+  Molecule right_ending = slice;
+  right_ending.translate_axis (x_extent[RIGHT] - slice_x_extent[RIGHT],
+                              X_AXIS);
+  line.add_molecule (right_ending);
+
+  // Fill out space between left and right ending of ledger line by
+  // lining up a series of slices in a row between them.
+  Molecule fill_out_slice = left_ending;
+  Real thick = slice_y_extent.length();
+  Real delta_x = slice_x_extent.length () - thick;
+  Real xpos = x_extent [LEFT] + 2*delta_x + thick/2; // TODO: check: thick*2?
+  while (xpos <= x_extent[RIGHT])
+    {
+      fill_out_slice.translate_axis (delta_x, X_AXIS);
+      line.add_molecule (fill_out_slice);
+      xpos += delta_x;
+    }
+
+  return line;
+}
+
+void add_streepjes(Score_element* me,
+                  int pos,
+                  int interspaces,
+                  Molecule* custos_p_)
+{
+  // TODO: This is (almost) duplicated code (see
+  // Note_head::brew_molecule).  Junk me.
+  Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
+  int streepjes_i = abs (pos) < interspaces
+    ? 0
+    : (abs(pos) - interspaces) /2;
+  if (streepjes_i) 
+    {
+      Direction dir = (Direction)sign (pos);
+      Molecule ledger_line (create_ledger_line (custos_p_->extent (X_AXIS),
+                                               me));
+      ledger_line.set_empty (true);
+      Real offs = (Staff_symbol_referencer::on_staffline (me))
+       ? 0.0
+       : -dir * inter_f;
+      for (int i = 0; i < streepjes_i; i++)
+       {
+         Molecule streep (ledger_line);
+         streep.translate_axis (-dir * inter_f * i * 2 + offs,
+                                Y_AXIS);
+         custos_p_->add_molecule (streep);
+       }
+    }
+}
+
+MAKE_SCHEME_CALLBACK(Custos,brew_molecule,1);
+SCM
+Custos::brew_molecule (SCM smob)
+{
+  Item *me = (Item *)unsmob_element (smob);
+  SCM scm_style = me->get_elt_property ("style");
+
+  if (gh_string_p (scm_style))
+    {
+      String style = ly_scm2string (scm_style);
+
+      String idx = "custodes-";
+      int interspaces = Staff_symbol_referencer::line_count (me)-1;
+
+      Real pos = Staff_symbol_referencer::position_f (me);
+      
+      if (pos > (interspaces/2 + 1)) // TODO: make this rule configurable
+       idx += "r";
+      idx += style;
+      Molecule molecule
+       = Font_interface::get_default_font (me)->find_by_name (idx);
+      if (molecule.empty_b())
+        {
+         String message = "unknown custos style: `" + style + "'";
+         warning(_ (message.ch_C()));
+         return SCM_EOL;
+       }
+      else
+        {
+         add_streepjes(me, (int)pos, interspaces, &molecule);
+         SCM result = molecule.create_scheme();
+         return result;
+       }
+    }
+  else
+    return SCM_EOL;
+}
+
+bool
+Custos::has_interface (Score_element*m)
+{
+  return m && m->has_interface (ly_symbol2scm ("custos-interface"));
+}
diff --git a/lily/include/custos.hh b/lily/include/custos.hh
new file mode 100644 (file)
index 0000000..d962ef9
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+  custos.hh
+
+  source file of the GNU LilyPond music typesetter
+
+  (C) 2000 Juergen Reuter <reuterj@ira.uka.de>
+*/
+
+#ifndef CUSTOS_HH
+#define CUSTOS_HH
+
+#include "lily-guile.hh"
+
+struct Custos
+{
+  DECLARE_SCHEME_CALLBACK(brew_molecule, (SCM ));
+  static bool has_interface (Score_element*);
+};
+
+#endif // CUSTOS_HH
+