Hi!

Attached is a patch that introduces ligature brackets (anyone knows a
better term for these beasts?).  These brackets are used in modern
notation when transcribing mensural music; they simply mark a series
of notes that, in the original notation, formed a ligature.

Example:

c d e \[ f g a g \] f e d c

This puts square edges around the notes f g a g.  This, of course,
could have been implemented simplier, namely without using a spanner.
However, for future extensions, I think a spanner fits best.  I am
planning to use this syntax to enclose ligatures in general (i.e. not
only mensural or transcribed ones).

Greetings,
Juergen
diff -Naur lilypond-1.5.52/ChangeLog lilypond-1.5.52.NEW/ChangeLog
--- lilypond-1.5.52/ChangeLog   Fri Apr 12 19:44:59 2002
+++ lilypond-1.5.52.NEW/ChangeLog       Tue Apr 16 01:16:13 2002
@@ -1,3 +1,15 @@
+2002-04-15  Juergen Reuter  <[EMAIL PROTECTED]>
+
+       * scm/grob-description.scm, lily/staff-symbol.cc: added properties
+       to control width of staff symbol in ragged-right mode (by request
+       of Han-Wen)
+
+       * ly/engraver-init.ly, lily/include/my-lily-parser.hh,
+       lily/include/ligature-bracket.hh, lily/lexer.ll, lily/parser.yy,
+       lily/ligature-bracket.cc, lily/ligature-bracket-engraver.cc:
+       added support for ligature brackets (needed when transcribing
+       mensural music)
+
 2002-04-12  Han-Wen Nienhuys  <[EMAIL PROTECTED]>
 
        * lily/*.cc: add some undocced properties.
diff -Naur lilypond-1.5.52/lily/include/ligature-bracket.hh 
lilypond-1.5.52.NEW/lily/include/ligature-bracket.hh
--- lilypond-1.5.52/lily/include/ligature-bracket.hh    Thu Jan  1 01:00:00 1970
+++ lilypond-1.5.52.NEW/lily/include/ligature-bracket.hh        Sun Apr 14 04:30:04 
+2002
@@ -0,0 +1,25 @@
+/*
+  ligature-bracket.hh -- part of GNU LilyPond
+
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2002 Juergen Reuter <[EMAIL PROTECTED]>
+*/
+
+#ifndef LIGATURE_BRACKET_HH
+#define LIGATURE_BRACKET_HH
+
+#include "lily-proto.hh"
+#include "lily-guile.hh"
+
+class Ligature_bracket
+{
+public:
+  Ligature_bracket (SCM);
+  DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
+
+private:
+};
+
+#endif /* LIGATURE_BRACKET_HH */
+
diff -Naur lilypond-1.5.52/lily/include/my-lily-parser.hh 
lilypond-1.5.52.NEW/lily/include/my-lily-parser.hh
--- lilypond-1.5.52/lily/include/my-lily-parser.hh      Sat Mar 23 03:42:23 2002
+++ lilypond-1.5.52.NEW/lily/include/my-lily-parser.hh  Sat Apr 13 20:10:47 2002
@@ -51,7 +51,9 @@
 
   SCM last_beam_start_;
   void beam_check (SCM); 
-  
+
+  SCM last_ligature_start_;
+
   Input here_input () const;
   void push_spot ();
   Input pop_spot ();
diff -Naur lilypond-1.5.52/lily/lexer.ll lilypond-1.5.52.NEW/lily/lexer.ll
--- lilypond-1.5.52/lily/lexer.ll       Fri Mar  1 01:41:05 2002
+++ lilypond-1.5.52.NEW/lily/lexer.ll   Sat Apr 13 20:00:54 2002
@@ -460,6 +460,10 @@
        return E_OPEN;
     case ')':
        return E_CLOSE;
+    case '[':
+       return E_LEFTSQUARE;
+    case ']':
+       return E_RIGHTSQUARE;
     case '~':
        return E_TILDE;
     case '\\':
diff -Naur lilypond-1.5.52/lily/ligature-bracket-engraver.cc 
lilypond-1.5.52.NEW/lily/ligature-bracket-engraver.cc
--- lilypond-1.5.52/lily/ligature-bracket-engraver.cc   Thu Jan  1 01:00:00 1970
+++ lilypond-1.5.52.NEW/lily/ligature-bracket-engraver.cc       Mon Apr 15 03:27:25 
+2002
@@ -0,0 +1,193 @@
+/*   
+  ligature-bracket-engraver.cc -- implement Ligature__bracket_engraver
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2002 Juergen Reuter <[EMAIL PROTECTED]>
+  
+ */
+#include "engraver.hh"
+#include "musical-request.hh"
+#include "warn.hh"
+#include "drul-array.hh"
+#include "item.hh"
+#include "spanner.hh"
+#include "score-engraver.hh"
+#include "note-head.hh"
+#include "stem.hh"
+#include "rest.hh"
+
+class Ligature_bracket_engraver : public Engraver
+{
+  Drul_array<Span_req*> reqs_drul_;
+  
+  Spanner *finished_ligature_bracket_p_;
+  Spanner *ligature_bracket_p_;
+  Span_req *prev_start_req_;
+
+  // moment where ligature started.
+  Moment ligature_start_mom_;
+  Grob *last_bound;
+
+protected:
+  virtual void stop_translation_timestep ();
+  virtual void start_translation_timestep ();
+  virtual void finalize ();
+
+  virtual void acknowledge_grob (Grob_info);
+  virtual bool try_music (Music*);
+  virtual void process_music ();
+
+public:
+  TRANSLATOR_DECLARATIONS(Ligature_bracket_engraver);
+
+private:
+  void typeset_ligature_bracket ();
+};
+
+
+Ligature_bracket_engraver::Ligature_bracket_engraver ()
+{
+  ligature_bracket_p_ = 0;
+  finished_ligature_bracket_p_ = 0;
+  reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
+  prev_start_req_ = 0;
+  last_bound = 0;
+}
+
+bool
+Ligature_bracket_engraver::try_music (Music *m)
+{
+  if (Span_req *req_ = dynamic_cast<Span_req*> (m))
+    {
+      if (scm_equal_p (req_->get_mus_property ("span-type"),
+                      ly_str02scm ("abort")) == SCM_BOOL_T)
+       {
+         reqs_drul_[START] = 0;
+         reqs_drul_[STOP] = 0;
+         if (ligature_bracket_p_)
+           ligature_bracket_p_->suicide ();
+         ligature_bracket_p_ = 0;
+       }
+      else if (scm_equal_p (req_->get_mus_property ("span-type"),
+                           ly_str02scm ("ligature-bracket")) == SCM_BOOL_T)
+       {
+         Direction d = req_->get_span_dir ();
+         reqs_drul_[d] = req_;
+         return true;
+       }
+    }
+  return false;
+}
+
+void
+Ligature_bracket_engraver::process_music ()
+{
+  if (reqs_drul_[STOP])
+    {
+      if (!ligature_bracket_p_)
+       reqs_drul_[STOP]->origin ()->warning (_ ("can't find start of ligature"));
+      else
+       {
+         if (!last_bound)
+           {
+             reqs_drul_[STOP]->origin ()->warning (_ ("no right bound"));
+           }
+         else
+           {
+             ligature_bracket_p_->set_bound (RIGHT, last_bound);
+           }
+       }
+      prev_start_req_ = 0;
+      finished_ligature_bracket_p_ = ligature_bracket_p_;
+      ligature_bracket_p_ = 0;
+    }
+  last_bound = unsmob_grob (get_property ("currentMusicalColumn"));
+
+  if (ligature_bracket_p_)
+    {
+      // TODO: maybe forbid breaks only if not transcribing
+      top_engraver ()->forbid_breaks ();
+    }
+  if (reqs_drul_[START])
+    {
+      if (ligature_bracket_p_)
+       {
+         reqs_drul_[START]->origin ()->warning (_ ("already have a ligature"));
+         return;
+       }
+
+      prev_start_req_ = reqs_drul_[START];
+      ligature_bracket_p_ = new Spanner (get_property ("LigatureBracket"));
+
+      Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
+      if (!bound)
+       {
+         reqs_drul_[START]->origin ()->warning (_ ("no left bound"));
+       }
+      else
+       {
+         ligature_bracket_p_->set_bound (LEFT, bound);
+       }
+
+      ligature_start_mom_ = now_mom ();
+      
+      announce_grob(ligature_bracket_p_, reqs_drul_[START]->self_scm());
+    }
+}
+
+void
+Ligature_bracket_engraver::start_translation_timestep ()
+{
+  reqs_drul_[START] = 0;
+  reqs_drul_[STOP] = 0;
+}
+
+void
+Ligature_bracket_engraver::typeset_ligature_bracket ()
+{
+  if (finished_ligature_bracket_p_)
+    {
+      typeset_grob (finished_ligature_bracket_p_);
+      finished_ligature_bracket_p_ = 0;
+    }
+}
+
+void
+Ligature_bracket_engraver::stop_translation_timestep ()
+{
+  typeset_ligature_bracket ();
+}
+
+void
+Ligature_bracket_engraver::finalize ()
+{
+  typeset_ligature_bracket ();
+  if (ligature_bracket_p_)
+    {
+      prev_start_req_->origin ()->warning (_ ("unterminated ligature"));
+      ligature_bracket_p_->suicide ();
+    }
+}
+
+void
+Ligature_bracket_engraver::acknowledge_grob (Grob_info info)
+{
+  if (ligature_bracket_p_)
+    {
+      if (Rest::has_interface (info.grob_l_))
+       {
+         reqs_drul_[START]->origin ()->warning (_ ("ligature may not contain rest; 
+ignoring rest"));
+         prev_start_req_->origin ()->warning (_ ("ligature was started here"));
+         // TODO: maybe better should stop ligature here rather than
+         // ignoring the rest?
+       }
+    }
+}
+
+ENTER_DESCRIPTION(Ligature_bracket_engraver,
+/* descr */       "Handles Ligature_requests by engraving Ligature brackets.",
+/* creats*/       "LigatureBracket",
+/* acks  */       "rest-interface",
+/* reads */       "",
+/* write */       "");
diff -Naur lilypond-1.5.52/lily/ligature-bracket.cc 
lilypond-1.5.52.NEW/lily/ligature-bracket.cc
--- lilypond-1.5.52/lily/ligature-bracket.cc    Thu Jan  1 01:00:00 1970
+++ lilypond-1.5.52.NEW/lily/ligature-bracket.cc        Mon Apr 15 03:17:58 2002
@@ -0,0 +1,145 @@
+/*
+  ligature-bracket.cc -- implement Ligature_bracket
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2002 Juergen Reuter <[EMAIL PROTECTED]>
+*/
+
+#include "ligature-bracket.hh"
+#include "item.hh"
+#include "paper-def.hh"
+#include "spanner.hh"
+#include "staff-symbol-referencer.hh"
+#include "lookup.hh"
+#include "box.hh"
+
+static Molecule
+brew_edge (Direction dir, Real thickness, Real width, Real height,
+          Real blotdiameter)
+{
+  Molecule hline = Lookup::roundfilledbox (Box (Interval (0, width),
+                                               Interval (0, thickness)),
+                                          blotdiameter);
+  hline.translate_axis (height - thickness, Y_AXIS);
+
+  Molecule vline = Lookup::roundfilledbox (Box (Interval (0, thickness),
+                                               Interval (0, height)),
+                                          blotdiameter);
+  if (dir == RIGHT)
+    {
+      vline.translate_axis (width - thickness, X_AXIS);
+    }
+
+  Molecule edge = Molecule ();
+  edge.add_molecule (hline);
+  edge.add_molecule (vline);
+  return edge;
+}
+
+MAKE_SCHEME_CALLBACK (Ligature_bracket, brew_molecule, 1);
+SCM
+Ligature_bracket::brew_molecule (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Spanner *spanner = dynamic_cast<Spanner*> (me);
+  Real blotdiameter = me->paper_l ()->get_var ("blotdiameter");
+  Real staff_space = Staff_symbol_referencer::staff_space (me);
+
+  Real thickness = me->paper_l ()->get_var ("linethickness");  
+  SCM grob_thickness = me->get_grob_property ("thickness");
+  if (gh_number_p (grob_thickness))
+    thickness *= gh_scm2double (grob_thickness);
+
+  SCM edge_width_scm = me->get_grob_property ("width");
+  Real edge_width;
+  if (gh_number_p (edge_width_scm))
+    {
+      edge_width = gh_scm2double (edge_width_scm);
+    }
+  else
+    {
+      edge_width = 0.75;
+    }
+  edge_width *= staff_space;
+
+  SCM edge_height_scm = me->get_grob_property ("height");
+  Real edge_height;
+  if (gh_number_p (edge_height_scm))
+    {
+      edge_height = gh_scm2double (edge_height_scm);
+    }
+  else
+    {
+      edge_height = 0.5;
+    }
+  edge_height *= staff_space;
+
+  Item* left_bound = spanner->get_bound (LEFT);
+  Item* right_bound = spanner->get_bound (RIGHT);
+
+  Molecule bracket = Molecule ();
+
+  Real y_min_offs =
+    0.5 * Staff_symbol_referencer::line_count (me) * staff_space;
+  Real y_left_offs = y_min_offs;
+  Real y_right_offs = y_min_offs;
+
+  Real left_bound_left_extent = 0;
+
+  if (left_bound)
+    {
+      Molecule left_edge =
+       brew_edge (LEFT, thickness, edge_width, edge_height, blotdiameter);
+      Grob *left_common_x = me->common_refpoint (left_bound, X_AXIS);
+      left_bound_left_extent =
+       left_bound->extent (left_common_x, X_AXIS)[LEFT];
+      left_edge.translate_axis (left_bound_left_extent, X_AXIS);
+      bracket.add_molecule (left_edge);
+      Grob *left_common_y = me->common_refpoint (left_bound, Y_AXIS);
+      y_left_offs =
+       max(y_left_offs, left_bound->extent (left_common_y, Y_AXIS)[UP]);
+    }
+  else
+    {
+      me->warning (_ ("no left bound"));
+    }
+
+  if (right_bound)
+    {
+      Molecule right_edge =
+       brew_edge (RIGHT, thickness, edge_width, edge_height, blotdiameter);
+      Grob *staff_symbol = Staff_symbol_referencer::staff_symbol_l (me);
+      Grob *right_common_bound_x =
+       right_bound->common_refpoint (staff_symbol, X_AXIS);
+
+      Real left_offs = 0;
+      if (left_bound)
+       {
+         Grob *left_common_bound_x =
+           left_bound->common_refpoint (staff_symbol, X_AXIS);
+         left_offs = left_bound->extent (left_common_bound_x, X_AXIS)[LEFT];
+       }
+
+      Real right_offs =
+       right_bound->extent (right_common_bound_x, X_AXIS)[RIGHT];
+
+      right_edge.translate_axis (+ right_offs
+                                - left_offs
+                                + left_bound_left_extent
+                                - edge_width,
+                                X_AXIS);
+      bracket.add_molecule (right_edge);
+      Grob *right_common_y = me->common_refpoint (right_bound, Y_AXIS);
+      y_right_offs =
+       max(y_right_offs, right_bound->extent (right_common_y, Y_AXIS)[UP]);
+    }
+  else
+    {
+      me->warning (_ ("no left bound"));
+    }
+
+  bracket.translate_axis (max (y_left_offs, y_right_offs), Y_AXIS);
+
+  return bracket.smobbed_copy ();
+}
diff -Naur lilypond-1.5.52/lily/parser.yy lilypond-1.5.52.NEW/lily/parser.yy
--- lilypond-1.5.52/lily/parser.yy      Sat Mar 23 03:42:23 2002
+++ lilypond-1.5.52.NEW/lily/parser.yy  Mon Apr 15 01:42:48 2002
@@ -244,7 +244,8 @@
 %token REST
 
 /* escaped */
-%token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE E_TILDE
+%token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
+%token E_LEFTSQUARE E_RIGHTSQUARE E_TILDE
 %token E_BACKSLASH
 %token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
 %token FIGURE_SPACE
@@ -1236,6 +1237,19 @@
                Span_req*b= new Span_req;
                b->set_span_dir ( STOP);
                b->set_mus_property ("span-type", ly_str02scm ("beam"));
+               $$ = b;
+       }
+       | E_LEFTSQUARE {
+               Span_req *b = new Span_req;
+               b->set_span_dir (START);
+               b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
+               $$ = b;
+               THIS->last_ligature_start_ = b->self_scm ();
+       }
+       | E_RIGHTSQUARE {
+               Span_req *b = new Span_req;
+               b->set_span_dir (STOP);
+               b->set_mus_property ("span-type", ly_str02scm ("ligature-bracket"));
                $$ = b;
        }
        | BREATHE {
diff -Naur lilypond-1.5.52/lily/staff-symbol.cc 
lilypond-1.5.52.NEW/lily/staff-symbol.cc
--- lilypond-1.5.52/lily/staff-symbol.cc        Wed Apr 10 19:11:39 2002
+++ lilypond-1.5.52.NEW/lily/staff-symbol.cc    Sat Apr 13 19:55:43 2002
@@ -13,6 +13,7 @@
 #include "debug.hh"
 #include "item.hh"
 #include "staff-symbol.hh"
+#include "staff-symbol-referencer.hh"
 #include "spanner.hh"
 
 
@@ -27,23 +28,38 @@
   Grob * common
     = sp->get_bound (LEFT)->common_refpoint (sp->get_bound (RIGHT), X_AXIS);
   
-  bool ragged = to_boolean (me->paper_l ()->get_scmvar ("raggedright"));
+  bool paper_raggedright = to_boolean (me->paper_l ()->get_scmvar ("raggedright"));
+  bool grob_raggedright = to_boolean (me->get_grob_property ("ragged-right"));
   Real width;
-  if (ragged)
+
+  SCM width_scm = me->get_grob_property ("width");
+  if (gh_number_p (width_scm)) // user-defined width
     {
-      // *prevent* staff symbol from being ragged right
       width =
-       me->paper_l ()->get_var ("linewidth")
-       - sp->get_bound (LEFT)->relative_coordinate (common, X_AXIS)
-       ;
+       gh_scm2double (width_scm) *
+       Staff_symbol_referencer::staff_space (me);
     }
-  else
+  else // determine width automatically
     {
-      width =
-       // right_shift     - left_shift
-       + sp->get_bound (RIGHT)->relative_coordinate (common , X_AXIS)
-       - sp->get_bound (LEFT)->relative_coordinate (common, X_AXIS)
-       ;
+      if (paper_raggedright && !grob_raggedright)
+       {
+         // *prevent* staff symbol from being ragged right; instead, use
+         // paper variable "linewidth"
+         width = me->paper_l ()->get_var ("linewidth");
+       }
+      else // determine width from my own bounds
+       {
+         width = sp->get_bound (RIGHT)->relative_coordinate (common , X_AXIS);
+       }
+    }
+
+  // respect indentation, if any
+  width -= sp->get_bound (LEFT)->relative_coordinate (common, X_AXIS);
+
+  if (width < 0)
+    {
+      warning (_f ("staff symbol: indentation yields beyond end of line"));
+      width = 0;
     }
 
   Real t = me->paper_l ()->get_var ("linethickness");
diff -Naur lilypond-1.5.52/ly/engraver-init.ly lilypond-1.5.52.NEW/ly/engraver-init.ly
--- lilypond-1.5.52/ly/engraver-init.ly Fri Apr 12 19:34:02 2002
+++ lilypond-1.5.52.NEW/ly/engraver-init.ly     Sun Apr 14 22:10:26 2002
@@ -131,7 +131,8 @@
        \consists "Arpeggio_engraver"
        \consists "Multi_measure_rest_engraver"
        \consists "Text_spanner_engraver"
-       
+
+       \consists "Ligature_bracket_engraver"
        \consists "Breathing_sign_engraver"
        % \consists "Rest_engraver"
        \consists "Stem_engraver"
diff -Naur lilypond-1.5.52/scm/grob-description.scm 
lilypond-1.5.52.NEW/scm/grob-description.scm
--- lilypond-1.5.52/scm/grob-description.scm    Fri Apr 12 19:39:16 2002
+++ lilypond-1.5.52.NEW/scm/grob-description.scm        Sun Apr 14 22:02:06 2002
@@ -358,6 +358,13 @@
        (meta . ((interfaces . (key-signature-interface  font-interface  
break-aligned-interface))))
        ))
 
+    (LigatureBracket
+     . (
+       (width . 0.75)
+       (height . 0.5)
+       (molecule-callback . ,Ligature_bracket::brew_molecule)
+       (meta . ((interfaces . (ligature-bracket-interface))))
+       ))
 
     (LyricHyphen
      . (
@@ -702,6 +709,7 @@
      . (
        (molecule-callback . ,Staff_symbol::brew_molecule)
        (line-count . 5)
+       (ragged-right . #f)
        (layer . 0)
        (meta . ((interfaces . (staff-symbol-interface))))
        ))
diff -Naur lilypond-1.5.52/scm/grob-property-description.scm 
lilypond-1.5.52.NEW/scm/grob-property-description.scm
--- lilypond-1.5.52/scm/grob-property-description.scm   Fri Apr 12 19:42:53 2002
+++ lilypond-1.5.52.NEW/scm/grob-property-description.scm       Sat Apr 13 19:47:51 
+2002
@@ -271,6 +271,7 @@
 
 (grob-property-description 'pitches list? "list of musical-pitch.")
 (grob-property-description 'positions pair? "cons of staff positions (LEFT . RIGHT")
+(grob-property-description 'ragged-right boolean? "In ragged alignment mode (i.e. if 
+paper variable @code{raggedright} is set), rag staff symbols only if this staff 
+symbol grob property is also set.")
 (grob-property-description 'raise number? "height for text to be raised (a negative 
value lowers the text.")
 (grob-property-description 'right-padding number? "space right of accs.")
 (grob-property-description 'right-trim-amount number? "shortening of the lyric 
extender on the right.")

Reply via email to