]> git.donarmstrong.com Git - lilypond.git/commitdiff
* lily/stem.cc (head_count): Change function name. Change property
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Tue, 23 Apr 2002 09:51:08 +0000 (09:51 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Tue, 23 Apr 2002 09:51:08 +0000 (09:51 +0000)
to #'note-heads i.s.o.  #'heads.
(position_noteheads): Kern noteheads for invisible stems.
(before_line_breaking): Do position_noteheads() for whole note
heads too.

* lily/accidental-placement.cc (position_accidentals): First
determine refpoints, only then determine extents.

16 files changed:
ChangeLog
flower/include/interval.hh
input/regression/accidental-placement.ly
input/regression/completion-heads.ly [new file with mode: 0644]
input/regression/note-head-chord.ly [new file with mode: 0644]
lily/accidental-placement.cc
lily/auto-beam-engraver.cc
lily/include/stem.hh
lily/skyline.cc
lily/stem.cc
mf/feta-nummer16.mf [new file with mode: 0644]
mf/feta-nummer20.mf [new file with mode: 0644]
mf/feta-nummer23.mf [new file with mode: 0644]
mf/feta-nummer26.mf [new file with mode: 0644]
scm/grob-property-description.scm
scripts/lilypond-book.py

index 70a650e6080d35b11be76e54dc1323fca714f325..cf7b8cb15de9ddb8d9188a028daa2f4a8cbe44ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2002-04-23  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
+
+       * lily/stem.cc (head_count): Change function name. Change property
+       to #'note-heads i.s.o.  #'heads.
+       (position_noteheads): Kern noteheads for invisible stems.
+       (before_line_breaking): Do position_noteheads() for whole note
+       heads too.
+
+       * lily/accidental-placement.cc (position_accidentals): First
+       determine refpoints, only then determine extents.  
+
 2002-04-22  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
 
        * lily/accidental-placement.cc (position_accidentals): use all
index 261a1c37afb99ae1f7e64a5aa980fdc5d792144d..c4e9d4e718de4322915e999db7b9d21eaa2a26d0 100644 (file)
@@ -24,7 +24,7 @@ struct Interval_t : public Drul_array<T> {
     
   static T infinity () ;
   static String T_to_str (T arg);
-  T center () {
+  T center () const {
     assert (!empty_b ());
     return (elem (LEFT) + elem (RIGHT)) / T (2);
   }
index 0b22b665e86d7b47253d8a8f25216690975a9a12..3653addaef965c5a0d91fcb9c9eb352689e37086 100644 (file)
@@ -11,6 +11,7 @@ Accidentals in corresponding octaves are aligned."
     <bes! cis!>
     <c! es ges beses>
     <bes! c d f >    
+    <bes,! c d f >
 }
 \paper { linewidth = -1. }
      }
diff --git a/input/regression/completion-heads.ly b/input/regression/completion-heads.ly
new file mode 100644 (file)
index 0000000..6790220
--- /dev/null
@@ -0,0 +1,24 @@
+\version "1.5.50"
+
+\header{
+texidoc="
+
+If the Note_heads_engraver is replaced by the Completion_heads_engraver, 
+notes that cross bar lines are split into tied notes.
+"
+}
+
+\score{
+  \notes\relative c'{
+  \time 2/4
+
+  c2. c8 d4 e f g a b c8 c2 b4 a g16 f4 e d c8. c2 
+  }
+  \paper{
+    \translator{
+      \ThreadContext
+      \remove "Note_heads_engraver"
+      \consists "Completion_heads_engraver"
+    }
+  }
+}
\ No newline at end of file
diff --git a/input/regression/note-head-chord.ly b/input/regression/note-head-chord.ly
new file mode 100644 (file)
index 0000000..bfdd455
--- /dev/null
@@ -0,0 +1,16 @@
+
+\header {
+    texidoc = "Note heads are flipped on the stem to prevent collisions.
+It also works for whole heads that have invisible stems.
+"
+
+}
+
+\score { \notes \relative c''
+        \context Thread {
+            <g4 a c>
+            <c d g a>
+            <c d e >
+            <c c g>
+            <c1 d f g>
+    }}
index 5a8693b8abb17b95dd0c138193a46082245d1c74..84e3c6c245dc8a62d083008e2e94a661190d4bda 100644 (file)
@@ -100,11 +100,27 @@ struct Accidental_placement_entry
   }
 };
 
+static Interval all_accidental_vertical_extent;
+Real ape_priority (Accidental_placement_entry const * a)
+{
+  Real c = a->vertical_extent_.center();
+
+  /*
+    far from center means we can fold more. Hopefully.
+   */
+  Real center_distance =
+    fabs(c - all_accidental_vertical_extent[LEFT]) >?
+    fabs(c - all_accidental_vertical_extent[RIGHT]);
+  
+  return 20 * a->vertical_extent_.length  ()  + center_distance;
+}
+
+  
 
 int ape_compare (Accidental_placement_entry *const &a,
                 Accidental_placement_entry *const &b)
 {
-  return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
+  return sign (ape_priority (a) - ape_priority(b));
 }
 
 /*
@@ -158,23 +174,20 @@ Accidental_placement::position_accidentals (Grob * me)
 
 
   Grob *commony =0 ;
-  for (int i= apes.size (); i--;)
-    commony = common_refpoint_of_array  (apes[i]->grobs_, commony, Y_AXIS);
 
+  /*
+    First we must extract *all* pointers. We can only determine
+    extents if we're sure that we've found the right common refpoint
+   */
   Link_array<Grob> note_cols, heads;
   for (int i= apes.size (); i--;)
-    {
+    { 
       Accidental_placement_entry * ape = apes[i];
-      ape->left_skyline_ = empty_skyline ( LEFT);
-      ape->right_skyline_ = empty_skyline ( RIGHT);
-   
-      for (int j = apes[i]->grobs_.size(); j--;)
+      for (int j = ape->grobs_.size(); j--;)
        {
-         Grob * a = apes[i]->grobs_[j];
-         Box b;
-         b[X_AXIS] = a->extent (me, X_AXIS);
-         b[Y_AXIS] = a->extent (commony, Y_AXIS);
-
+         Grob * a = ape->grobs_[j];
+         
+         commony = commony->common_refpoint (a, Y_AXIS);
          Grob *head = a->get_parent (Y_AXIS);
 
          Grob * col = head->get_parent (X_AXIS);
@@ -182,18 +195,8 @@ Accidental_placement::position_accidentals (Grob * me)
            note_cols.push (col);
          else
            heads.push (head);
-         
-         ape->extents_.push (b);
-         
-         /*
-           TODO: replace the extents of a flat by combination of two
-           bboxes, so that we use the shape of the flat better.
-         */
-         insert_extent_into_skyline (&ape->left_skyline_, b, Y_AXIS, LEFT);
-         insert_extent_into_skyline (&ape->right_skyline_ , b,Y_AXIS, RIGHT);
        }
     }
-
   
   for (int i = note_cols.size() ; i--;)
     {
@@ -205,7 +208,34 @@ Accidental_placement::position_accidentals (Grob * me)
   heads.default_sort();
   heads.uniq();
   commony = common_refpoint_of_array (heads, commony, Y_AXIS);
+
   
+  for (int i= apes.size (); i--;)
+    {
+      Accidental_placement_entry * ape = apes[i];
+      ape->left_skyline_ = empty_skyline ( LEFT);
+      ape->right_skyline_ = empty_skyline ( RIGHT);
+   
+      for (int j = apes[i]->grobs_.size(); j--;)
+       {
+         Grob * a = apes[i]->grobs_[j];
+         Box b;
+         b[X_AXIS] = a->extent (me, X_AXIS);
+         b[Y_AXIS] = a->extent (commony, Y_AXIS);
+
+         ape->extents_.push (b);
+         
+         /*
+           TODO: replace the extents of a flat by combination of two
+           bboxes, so that we use the shape of the flat better.
+         */
+         insert_extent_into_skyline (&ape->left_skyline_, b, Y_AXIS, LEFT);
+         insert_extent_into_skyline (&ape->right_skyline_ , b,Y_AXIS, RIGHT);
+       }
+    }
+
+
+  Interval total;
   for (int i = apes.size(); i--;)
     {
       Interval y ;
@@ -215,8 +245,9 @@ Accidental_placement::position_accidentals (Grob * me)
          y.unite (apes[i]->extents_[j][Y_AXIS]);
        }
       apes[i]->vertical_extent_ = y;
+      total.unite (y);
     }
-  
+  all_accidental_vertical_extent = total;
   apes.sort (&ape_compare);  
 
   Accidental_placement_entry * head_ape = new Accidental_placement_entry;
@@ -244,20 +275,10 @@ Accidental_placement::position_accidentals (Grob * me)
     {
       Accidental_placement_entry *ape = apes[i];
       Real d = 0.0;
-      /*
-       confusing naming: left_skyline is a skyline pointing to the
-       left. It is on the right of the curent entry.
-       */
-
       int j = i+1;
       do {
-       Array<Skyline_entry> const *right_sky =
-         (j < apes.size())
-         ? &apes[j]->left_skyline_
-         : &head_skyline;
-
        d = - skyline_meshing_distance (ape->right_skyline_,
-                                            *right_sky);
+                                       apes[j]->left_skyline_);
 
        if (!isinf(d)
            || j + 1 == apes.size())
index 7c418a024b1913ee3c0b91e862b48c4164332c4d..5126db27dbea7046bf1c20bb4c46a6fd4120ffee 100644 (file)
@@ -370,7 +370,7 @@ Auto_beam_engraver::acknowledge_grob (Grob_info info)
       /*
        Don't (start) auto-beam over empty stems; skips or rests
        */
-      if (!Stem::heads_i (stem_l))
+      if (!Stem::head_count (stem_l))
        {
          if (stem_l_arr_p_)
            end_beam ();
index caa430cb42a835c8e9753fca36c414de0241d428..1c3b90883cff24f4478c0f9f8b54871a664fde2d 100644 (file)
@@ -33,7 +33,7 @@ public:
   static void set_stemend (Grob *,Real);
   static Direction get_default_dir (Grob *) ;
 
-  static int heads_i (Grob *) ;
+  static int head_count (Grob *) ;
   static bool invisible_b (Grob *) ;
   static Interval head_positions (Grob *) ;
   static Real get_default_stem_end_position (Grob*me) ;
index cc47448ee9d07143d774ea586719a9cd9e3b0d24..9857fe495506ac089005ec9054a897e1203eb151 100644 (file)
@@ -26,7 +26,7 @@
   This file deals with building such skyline structure, and computing
   the minimum distance between two opposing skylines.
   
-  
+   
   Invariants for a skyline:
 
   skyline[...].width_ forms a partition of the real interval, where
index 0f6591987ab71afc484e679fd73afe6d95f131a0..2b0874291e432a15b43b55ace5cfc8a1b8ae41ba 100644 (file)
@@ -56,7 +56,7 @@ Stem::beam_count (Grob*me,Direction d)
 Interval
 Stem::head_positions (Grob*me) 
 {
-  if (!heads_i (me))
+  if (!head_count (me))
     {
       Interval iv;
       return iv;
@@ -135,13 +135,13 @@ Stem::support_head (Grob*me)
   Grob * nh = unsmob_grob (h);
   if (nh)
     return nh;
-  else if (heads_i (me) == 1)
+  else if (head_count (me) == 1)
     {
       /*
        UGH.
        */
       
-      return unsmob_grob (ly_car (me->get_grob_property ("heads")));
+      return unsmob_grob (ly_car (me->get_grob_property ("note-heads")));
     }
   else
     return first_head (me);
@@ -149,9 +149,9 @@ Stem::support_head (Grob*me)
 
 
 int
-Stem::heads_i (Grob*me)
+Stem::head_count (Grob*me)
 {
-  return  Pointer_group_interface::count (me, "heads");
+  return  Pointer_group_interface::count (me, "note-heads");
 }
 
 /*
@@ -177,7 +177,7 @@ Stem::extremal_heads (Grob*me)
   Drul_array<Grob *> exthead;
   exthead[LEFT] = exthead[RIGHT] =0;
   
-  for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s))
+  for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s))
     {
       Grob * n = unsmob_grob (ly_car (s));
 
@@ -207,7 +207,7 @@ Array<int>
 Stem::note_head_positions (Grob *me)
 {
   Array<int> ps ;
-  for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s))
+  for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s))
     {
       Grob * n = unsmob_grob (ly_car (s));
       int p = int (Staff_symbol_referencer::position_f (n));
@@ -228,14 +228,14 @@ Stem::add_head (Grob*me, Grob *n)
 
   if (Note_head::has_interface (n))
     {
-      Pointer_group_interface::add_grob (me, ly_symbol2scm ("heads"), n);
+      Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"), n);
     }
 }
 
 bool
 Stem::invisible_b (Grob*me)
 {
-  return ! (heads_i (me) && Rhythmic_head::balltype_i (support_head (me)) >= 1);
+  return ! (head_count (me) && Rhythmic_head::balltype_i (support_head (me)) >= 1);
 }
 
 Direction
@@ -380,11 +380,11 @@ Stem::duration_log (Grob*me)
 void
 Stem::position_noteheads (Grob*me)
 {
-  if (!heads_i (me))
+  if (!head_count (me))
     return;
   
   Link_array<Grob> heads =
-    Pointer_group_interface__extract_grobs (me, (Grob*)0, "heads");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-heads");
 
   heads.sort (compare_position);
   Direction dir =get_direction (me);
@@ -393,6 +393,13 @@ Stem::position_noteheads (Grob*me)
     heads.reverse ();
 
 
+  bool invisible = invisible_b (me);
+  Real thick = 0.0;
+  if (invisible)
+        thick = gh_scm2double (me->get_grob_property ("thickness"))
+         * me->paper_l ()->get_var ("linethickness");
+      
+
   Grob *hed = support_head (me);
   Real w = Note_head::head_extent (hed,X_AXIS)[dir];
   for (int i=0; i < heads.size (); i++)
@@ -414,7 +421,26 @@ Stem::position_noteheads (Grob*me)
            {
              Real l = Note_head::head_extent (heads[i], X_AXIS).length ();
 
-             heads[i]->translate_axis (l * get_direction (me), X_AXIS);
+             Direction d = get_direction (me);
+             heads[i]->translate_axis (l * d, X_AXIS);
+
+             if (invisible_b(me))
+               heads[i]->translate_axis (-thick *2* d , X_AXIS);
+
+             
+            /* TODO:
+                
+             For some cases we should kern some more: when the
+             distance between the next or prev note is too large, we'd 
+             get large white gaps, eg.
+             
+               |
+              X|
+              |X  <- kern this.
+              |
+             X
+             
+             */
            }
          parity = !parity;
        }
@@ -431,7 +457,12 @@ Stem::before_line_breaking (SCM smob)
 {
   Grob*me = unsmob_grob (smob);
 
-  if (!invisible_b (me))
+
+  /*
+    Do the calculations for visible stems, but also for invisible stems
+    with note heads (i.e. half notes.)
+   */
+  if (head_count (me))
     {
       stem_end_position (me);  // ugh. Trigger direction calc.
       position_noteheads (me);
@@ -809,5 +840,5 @@ Stem::calc_stem_info (Grob*me)
 
 ADD_INTERFACE (Stem,"stem-interface",
   "A stem",
-  "adjust-if-on-staffline thickness stem-info beamed-lengths beamed-minimum-lengths lengths beam stem-shorten duration-log beaming neutral-direction stem-end-position support-head heads direction length style no-stem-extend flag-style dir-forced");
+  "adjust-if-on-staffline thickness stem-info beamed-lengths beamed-minimum-lengths lengths beam stem-shorten duration-log beaming neutral-direction stem-end-position support-head note-heads direction length style no-stem-extend flag-style dir-forced");
 
diff --git a/mf/feta-nummer16.mf b/mf/feta-nummer16.mf
new file mode 100644 (file)
index 0000000..92423b0
--- /dev/null
@@ -0,0 +1,2 @@
+design_size := 16;
+input feta-nummer;
diff --git a/mf/feta-nummer20.mf b/mf/feta-nummer20.mf
new file mode 100644 (file)
index 0000000..8ddfd9e
--- /dev/null
@@ -0,0 +1,2 @@
+design_size := 20.74;
+input feta-nummer;
diff --git a/mf/feta-nummer23.mf b/mf/feta-nummer23.mf
new file mode 100644 (file)
index 0000000..d324151
--- /dev/null
@@ -0,0 +1,2 @@
+design_size := 23;
+input feta-nummer;
diff --git a/mf/feta-nummer26.mf b/mf/feta-nummer26.mf
new file mode 100644 (file)
index 0000000..a9308dd
--- /dev/null
@@ -0,0 +1,2 @@
+design_size := 26;
+input feta-nummer;
index 6eb69c3ac02f363223c5be82daa9569f0b288048..e226f9082e1e888fcd48012e7a9a78383eb32a56 100644 (file)
@@ -188,11 +188,7 @@ is used by @ref{note-collision-interface}.")
 
 (grob-property-description 'grow-direction dir? "crescendo or decrescendo?.")
 (grob-property-description 'hair-thickness number? "thickness, measured in stafflinethickness.")
-(grob-property-description 'heads pair? "list of note heads,
-
-FIXME: in Tie this is a pair of grob pointers, pointing to the two heads of the  tie.
-
-.")
+(grob-property-description 'heads pair? "Pair of grob pointers, pointing to the two heads of the  tie.")
 (grob-property-description 'height number? "in staffspace.")
 (grob-property-description 'horizontal-shift integer? "integer that identifies ranking of note-column for horizontal shifting. This is used by @ref{note-collision-interface}.")
 (grob-property-description 'ideal-distances list? "(OBJ . (DIST . STRENGTH)) pairs.")
index 9710a8dcc0bd387998f78d5d95095f14d7a0b905..4cab883e7a651c256fbb53e8d50ad009d7ef27f4 100644 (file)
@@ -836,7 +836,7 @@ def chop_chunks(chunks, re_name, func, use_match=0):
         if c[0] == 'input':
             str = c[1]
             while str:
-               print re_name
+#              print re_name
                 m = get_re (re_name).search (str)
                 if m == None:
                     newchunks.append (('input', str))