- Drul_array<int> total;
- total[UP] = total[DOWN] = 0;
- Drul_array<int> count;
- count[UP] = count[DOWN] = 0;
- Direction d = DOWN;
-
- Link_array<Grob> stems
- = extract_grob_array (me, ly_symbol2scm ("stems"));
-
- for (int i = 0; i < stems.size (); i++)
- do
- {
- Grob *s = stems[i];
- Direction sd = get_grob_direction (s);
-
- int center_distance = max (int (- d * Stem::head_positions (s) [-d]), 0);
- int current = sd ? (1 + d * sd) / 2 : center_distance;
-
- if (current)
- {
- total[d] += current;
- count[d]++;
- }
- }
- while (flip (&d) != DOWN);
-
- SCM func = me->get_property ("dir-function");
- SCM s = scm_call_2 (func,
- scm_cons (scm_int2num (count[UP]),
- scm_int2num (count[DOWN])),
- scm_cons (scm_int2num (total[UP]),
- scm_int2num (total[DOWN])));
-
- if (scm_is_number (s) && scm_to_int (s))
- return to_dir (s);
-
- /* If dir is not determined: get default */
- return to_dir (me->get_property ("neutral-direction"));
+ extract_grob_set (me, "stems", stems);
+
+ Drul_array<Real> extremes (0.0, 0.0);
+ for (iterof (s, stems); s != stems.end (); s++)
+ {
+ Interval positions = Stem::head_positions (*s);
+ Direction d = DOWN;
+ do
+ {
+ if (sign (positions[d]) == d)
+ extremes[d] = d * max (d * positions[d], d * extremes[d]);
+ }
+ while (flip (&d) != DOWN);
+ }
+
+ Drul_array<int> total (0, 0);
+ Drul_array<int> count (0, 0);
+
+ bool force_dir = false;
+ for (vsize i = 0; i < stems.size (); i++)
+ {
+ Grob *s = stems[i];
+ Direction stem_dir = CENTER;
+ SCM stem_dir_scm = s->get_property_data ("direction");
+ if (is_direction (stem_dir_scm))
+ {
+ stem_dir = to_dir (stem_dir_scm);
+ force_dir = true;
+ }
+ else
+ stem_dir = to_dir (s->get_property ("default-direction"));
+
+ if (!stem_dir)
+ stem_dir = to_dir (s->get_property ("neutral-direction"));
+
+ if (stem_dir)
+ {
+ count[stem_dir] ++;
+ total[stem_dir] += max (int (- stem_dir * Stem::head_positions (s) [-stem_dir]), 0);
+ }
+ }
+
+
+ if (!force_dir)
+ {
+ if (abs (extremes[UP]) > -extremes[DOWN])
+ return DOWN;
+ else if (extremes[UP] < -extremes[DOWN])
+ return UP;
+ }
+
+ Direction dir = CENTER;
+ Direction d = CENTER;
+ if ((d = (Direction) sign (count[UP] - count[DOWN])))
+ dir = d;
+ else if (count[UP]
+ && count[DOWN]
+ && (d = (Direction) sign (total[UP] / count[UP] - total[DOWN]/count[DOWN])))
+ dir = d;
+ else if ((d = (Direction) sign (total[UP] - total[DOWN])))
+ dir = d;
+ else
+ dir = to_dir (me->get_property ("neutral-direction"));
+
+ return dir;