/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2002--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 2002--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
LilyPond is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
SCM cause = acc->get_parent (Y_AXIS)->get_property ("cause");
- Stream_event *mcause = unsmob_stream_event (cause);
+ Stream_event *mcause = unsmob<Stream_event> (cause);
if (!mcause)
{
programming_error ("note head has no event cause");
return 0;
}
- return unsmob_pitch (mcause->get_property ("pitch"));
+ return unsmob<Pitch> (mcause->get_property ("pitch"));
}
void
-Accidental_placement::add_accidental (Grob *me, Grob *a)
+Accidental_placement::add_accidental (Grob *me, Grob *a, bool stagger, long context_hash)
{
Pitch *p = accidental_pitch (a);
if (!p)
return;
a->set_parent (me, X_AXIS);
- a->set_property ("X-offset", Grob::x_parent_positioning_proc);
- int n = p->get_notename ();
+ long n = p->get_notename ();
SCM accs = me->get_object ("accidental-grobs");
- SCM key = scm_from_int (n);
- SCM entry = scm_assq (key, accs);
- if (entry == SCM_BOOL_F)
+ SCM key = scm_cons (scm_from_int (n), scm_from_long (stagger ? context_hash : 1));
+ // assoc because we're dealing with pairs
+ SCM entry = scm_assoc (key, accs);
+ if (scm_is_false (entry))
entry = SCM_EOL;
else
entry = scm_cdr (entry);
entry = scm_cons (a->self_scm (), entry);
- accs = scm_assq_set_x (accs, key, entry);
+ accs = scm_assoc_set_x (accs, key, entry);
me->set_object ("accidental-grobs", accs);
}
acs = scm_cdr (acs))
for (SCM s = scm_cdar (acs); scm_is_pair (s); s = scm_cdr (s))
{
- Grob *a = unsmob_grob (scm_car (s));
+ Grob *a = unsmob<Grob> (scm_car (s));
- if (unsmob_grob (a->get_object ("tie"))
+ if (unsmob<Grob> (a->get_object ("tie"))
&& !to_boolean (a->get_property ("forced")))
break_reminder->push_back (a);
else
bool ape_less (Accidental_placement_entry *const &a,
Accidental_placement_entry *const &b)
{
+ vsize size_a = a->grobs_.size ();
+ vsize size_b = b->grobs_.size ();
+ if (size_a != size_b)
+ return size_b < size_a;
+
return ape_priority (a) < ape_priority (b);
}
vector<Accidental_placement_entry *> asc = *apes;
vector_sort (asc, &ape_less);
+ // we do the staggering below based on size
+ // this ensures that if a placement has 4 entries, it will
+ // always be closer to the NoteColumn than a placement with 1
+ // this allows accidentals to be on-average closer to notes
+ // while still preserving octave alignment
+ vector<vector<Accidental_placement_entry *> > ascs;
+
+ vsize sz = INT_MAX;
+ for (vsize i = 0; i < asc.size (); i++)
+ {
+ vsize my_sz = asc[i]->grobs_.size ();
+ if (sz != my_sz)
+ ascs.push_back (vector<Accidental_placement_entry *> ());
+ ascs.back ().push_back (asc[i]);
+ sz = my_sz;
+ }
apes->clear ();
- int parity = 1;
- for (vsize i = 0; i < asc.size ();)
+ for (vsize i = 0; i < ascs.size (); i++)
{
- Accidental_placement_entry *a = 0;
- if (parity)
+ int parity = 1;
+ for (vsize j = 0; j < ascs[i].size ();)
{
- a = asc.back ();
- asc.pop_back ();
- }
- else
- a = asc[i++];
+ Accidental_placement_entry *a = 0;
+ if (parity)
+ {
+ a = ascs[i].back ();
+ ascs[i].pop_back ();
+ }
+ else
+ a = ascs[i][j++];
- apes->push_back (a);
- parity = !parity;
+ apes->push_back (a);
+ parity = !parity;
+ }
}
reverse (*apes);
Accidental_placement_entry *ape = new Accidental_placement_entry;
for (SCM t = scm_cdar (s); scm_is_pair (t); t = scm_cdr (t))
- ape->grobs_.push_back (unsmob_grob (scm_car (t)));
+ ape->grobs_.push_back (unsmob<Grob> (scm_car (t)));
apes.push_back (ape);
}
offset -= a->extent (a, X_AXIS).length () + padding;
}
- if (Skyline_pair *sky = Skyline_pair::unsmob (a->get_property ("horizontal-skylines")))
+ if (Skyline_pair *sky = unsmob<Skyline_pair> (a->get_property ("horizontal-skylines")))
{
Skyline_pair copy (*sky);
copy.raise (a->relative_coordinate (common[X_AXIS], X_AXIS));
Grob *head = acc->get_parent (Y_AXIS);
Grob *col = head->get_parent (X_AXIS);
- if (Note_column::has_interface (col))
+ if (has_interface<Note_column> (col))
note_cols.push_back (col);
else
ret.push_back (head);
for (vsize i = note_cols.size (); i--;)
{
Grob *c = note_cols[i]->get_parent (X_AXIS);
- if (Note_collision_interface::has_interface (c))
+ if (has_interface<Note_collision_interface> (c))
{
extract_grob_set (c, "elements", columns);
concat (note_cols, columns);
if (Grob *s = Rhythmic_head::get_stem (ret[i]))
ret.push_back (s);
- vector_sort (ret, less<Grob *> ());
- uniq (ret);
+ uniquify (ret);
return ret;
}
vector<Box> head_extents;
for (vsize i = heads_and_stems.size (); i--;)
head_extents.push_back (Box (heads_and_stems[i]->extent (common[X_AXIS], X_AXIS),
- heads_and_stems[i]->pure_height (common[Y_AXIS], 0, INT_MAX)));
+ heads_and_stems[i]->pure_y_extent (common[Y_AXIS], 0, INT_MAX)));
return Skyline (head_extents, Y_AXIS, LEFT);
}
{
Accidental_placement_entry *ape = apes[i];
- Real offset = -ape->horizontal_skylines_[RIGHT].distance (left_skyline);
+ Real offset = -ape->horizontal_skylines_[RIGHT]
+ .distance (left_skyline, 0.1);
if (isinf (offset))
offset = last_offset;
else
{
Real mh = ape->horizontal_skylines_[d].max_height ();
if (!isinf (mh))
- width.add_point (mh);
+ width.add_point (mh + offset);
}
last_offset = offset;
SCM
Accidental_placement::calc_positioning_done (SCM smob)
{
- Grob *me = unsmob_grob (smob);
+ Grob *me = unsmob<Grob> (smob);
if (!me->is_live ())
return SCM_BOOL_T;