+ return da;
+}
+
+void
+Bezier_bow::minimise_enclosed_area ()
+{
+ Real len = curve_.control_[3][X_AXIS];
+ Real beautiful = len * default_height (len) / 2.0;
+
+ DEBUG_OUT << to_str ("Beautiful: %f\n", beautiful);
+ DEBUG_OUT << to_str ("Length: %f\n", len);
+ int steps=2;
+ for (int i=0; i < steps; i++)
+ {
+ Real ff = fit_factor ();
+ if (!ff)
+ break;
+
+ DEBUG_OUT << to_str ("FitFac: %f\n", ff);
+
+ // slur must be higher at every point
+ if (ff > 1.01)
+ {
+ blow_fit ();
+ DEBUG_OUT << to_str ("Blown area: %f\n", calc_enclosed_area_f ());
+ }
+ else
+ DEBUG_OUT << to_str ("Init area: %f\n", calc_enclosed_area_f ());
+
+ Real area = calc_enclosed_area_f ();
+
+
+ if (area <= beautiful)
+ break;
+
+ Array<Offset> da = area_gradient_offset_arr ();
+
+ /*
+ Urg: empiric cs
+ Small slurs are easily too asymmetric,
+ while big slurs are too symmetric
+
+ This makes short slurs strictly x-bound,
+ long slurs become y-bound.
+ */
+ Real ypct = 0.50;
+ //Real xpct = (0.07 * len * len / 1000.0) <? 0.80;
+ Real xpct = (0.1 * len * len * len / 100000.0) <? 0.80;
+
+ Real yu = (abs (curve_.control_[1][Y_AXIS] / da[0][Y_AXIS])
+ <? abs (curve_.control_[2][Y_AXIS] / da[1][Y_AXIS]))
+ * ypct;
+ Real xu = (abs (curve_.control_[1][X_AXIS] / da[0][X_AXIS])
+ <? abs ((curve_.control_[3][X_AXIS]
+ - curve_.control_[2][X_AXIS]) / da[1][X_AXIS]))
+ * xpct;
+ Real u = yu <? xu;
+ DEBUG_OUT << to_str ("u (xu, yu): %f (%f, %f)\n", u, xu, yu);
+ DEBUG_OUT << to_str ("pct (x, y): (%f, %f)\n", xpct, ypct);
+
+ DEBUG_OUT << to_str ("da1: (%f, %f)\n", da[0][X_AXIS], da[0][Y_AXIS]);
+ DEBUG_OUT << to_str ("da2: (%f, %f)\n", da[1][X_AXIS], da[1][Y_AXIS]);
+
+ curve_.control_[1] -= da[0] * u;
+ curve_.control_[2] -= da[1] * u;
+ }