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-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
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);
}
<bes! cis!>
<c! es ges beses>
<bes! c d f >
+ <bes,! c d f >
}
\paper { linewidth = -1. }
}
--- /dev/null
+\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
--- /dev/null
+
+\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>
+ }}
}
};
+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));
}
/*
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);
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--;)
{
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 ;
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;
{
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())
/*
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 ();
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) ;
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
Interval
Stem::head_positions (Grob*me)
{
- if (!heads_i (me))
+ if (!head_count (me))
{
Interval iv;
return iv;
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);
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");
}
/*
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));
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));
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
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);
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++)
{
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;
}
{
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);
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");
--- /dev/null
+design_size := 16;
+input feta-nummer;
--- /dev/null
+design_size := 20.74;
+input feta-nummer;
--- /dev/null
+design_size := 23;
+input feta-nummer;
--- /dev/null
+design_size := 26;
+input feta-nummer;
(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.")
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))