/*
  bow.cc -- implement Bow

  source file of the GNU LilyPond music typesetter

  (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
      Jan Nieuwenhuizen <janneke@gnu.org>
*/

#include "bow.hh"
#include "debug.hh"
#include "paper-def.hh"
#include "molecule.hh"
#include "lookup.hh"
#include "bezier.hh"
#include "main.hh"

IMPLEMENT_IS_TYPE_B1(Bow,Directional_spanner);

Bow::Bow ()
{
  dy_f_drul_[LEFT] = dy_f_drul_[RIGHT] = 0.0;
  dx_f_drul_[LEFT] = dx_f_drul_[RIGHT] = 0.0;
  dash_i_ = 0;
}

Molecule*
Bow::brew_molecule_p () const
{
  Real thick = paper ()->get_var ("slur_thickness");
  Array<Offset> c = get_controls ();
  Real dy = c[3].y () - c[0].y ();
  Atom a;

  if (!dash_i_)
    a = lookup_l ()->slur (c);
  else
    a = lookup_l ()->dashed_slur (c, thick, dash_i_);

  if (check_debug && !monitor->silent_b ("Bow"))
    {
      static int i = 1;
      cout << "******" << i++ << "******" << endl;
      // gcc 2.7.2: ices
//      cout << "c0.y: " << c[0].y << endl;
      cout << "c0.y: " << c[0].y () << endl;
      cout << "c3.y: " << c[3].y () << endl;
      cout << "dy: " << dy << endl;
      cout << "dy_f_l: " << dy_f_drul_[LEFT] << endl;
      cout << "dy_f_r: " << dy_f_drul_[RIGHT] << endl;
      cout << "dy_f: " << dy_f_drul_[RIGHT] - dy_f_drul_[LEFT] << endl;
    }
  a.translate (Offset (dx_f_drul_[LEFT], dy_f_drul_[LEFT]));

  Molecule* mol_p = new Molecule;
  mol_p->add_atom (a);

  return mol_p;
}

Offset
Bow::center () const
{
  Real dy = dy_f_drul_[RIGHT] - dy_f_drul_[LEFT];

  Real dx = width ().length ();

  return Offset (dx / 2, dy);
}



/*
   
   ugh .  Control points are too crude measures.
 */
Interval
Bow::do_height () const
{
  Array<Offset> c (get_controls());

  Interval iv;
  for (int i=0; i < c.size (); i++)
    {
      Real y = c[i][Y_AXIS];
      iv.unite (Interval (y,y));
    }
  return iv;
}

Interval
Bow::do_width () const    
{
  Interval i = Spanner::do_width ();
  Real dx = i.length();
  return Interval (0, dx);
}

Array<Offset>
Bow::get_controls () const
{
  Bezier_bow b (paper ());
  b.set (get_encompass_offset_arr (), dir_);
  b.calc ();
  Array<Offset> controls;
  controls.set_size (8);
  for (int i = 0; i < 4; i++)
    controls[i] = b.control_[i];
  for (int i = 0; i < 4; i++)
    controls[i + 4] = b.return_[i];
  return controls;
}

Array<Offset>
Bow::get_encompass_offset_arr () const
{
  Offset d (dx_f_drul_[RIGHT] - dx_f_drul_[LEFT],
    dy_f_drul_[RIGHT] - dy_f_drul_[LEFT]);
  d.x() += width (). length ();

#define RESIZE_ICE
#ifndef RESIZE_ICE
  Array<Offset> notes;
  notes.push (Offset 0, 0));
  notes.push (d);
#else
  Array<Offset> notes (2);
  notes[0] = Offset (0, 0);
  notes[1] = Offset (d);
#endif

  return notes;
}

