/*
 * Copyright © 2020  Ebrahim Byagowi
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

#ifndef HB_DRAW_HH
#define HB_DRAW_HH

#include "hb.hh"


/*
 * hb_draw_funcs_t
 */

#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
  HB_DRAW_FUNC_IMPLEMENT (move_to) \
  HB_DRAW_FUNC_IMPLEMENT (line_to) \
  HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
  HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
  HB_DRAW_FUNC_IMPLEMENT (close_path) \
  /* ^--- Add new callbacks here */

struct hb_draw_funcs_t
{
  hb_object_header_t header;

  struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
  } func;

  struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
  } *user_data;

  struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
  } *destroy;

  void emit_move_to (void *draw_data, hb_draw_state_t &st,
		     float to_x, float to_y)
  { func.move_to (this, draw_data, &st,
		  to_x, to_y,
		  !user_data ? nullptr : user_data->move_to); }
  void emit_line_to (void *draw_data, hb_draw_state_t &st,
		     float to_x, float to_y)
  { func.line_to (this, draw_data, &st,
		  to_x, to_y,
		  !user_data ? nullptr : user_data->line_to); }
  void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
			  float control_x, float control_y,
			  float to_x, float to_y)
  { func.quadratic_to (this, draw_data, &st,
		       control_x, control_y,
		       to_x, to_y,
		       !user_data ? nullptr : user_data->quadratic_to); }
  void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
		      float control1_x, float control1_y,
		      float control2_x, float control2_y,
		      float to_x, float to_y)
  { func.cubic_to (this, draw_data, &st,
		   control1_x, control1_y,
		   control2_x, control2_y,
		   to_x, to_y,
		   !user_data ? nullptr : user_data->cubic_to); }
  void emit_close_path (void *draw_data, hb_draw_state_t &st)
  { func.close_path (this, draw_data, &st,
		     !user_data ? nullptr : user_data->close_path); }


  void
  HB_ALWAYS_INLINE
  move_to (void *draw_data, hb_draw_state_t &st,
	   float to_x, float to_y)
  {
    if (unlikely (st.path_open)) close_path (draw_data, st);

    if (st.slant_xy)
      to_x += to_y * st.slant_xy;

    st.current_x = to_x;
    st.current_y = to_y;
  }

  void
  HB_ALWAYS_INLINE
  line_to (void *draw_data, hb_draw_state_t &st,
	   float to_x, float to_y)
  {
    if (unlikely (!st.path_open)) start_path (draw_data, st);

    if (st.slant_xy)
      to_x += to_y * st.slant_xy;

    emit_line_to (draw_data, st, to_x, to_y);

    st.current_x = to_x;
    st.current_y = to_y;
  }

  void
  HB_ALWAYS_INLINE
  quadratic_to (void *draw_data, hb_draw_state_t &st,
		float control_x, float control_y,
		float to_x, float to_y)
  {
    if (unlikely (!st.path_open)) start_path (draw_data, st);

    if (st.slant_xy)
    {
      control_x += control_y * st.slant_xy;
      to_x += to_y * st.slant_xy;
    }

    emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);

    st.current_x = to_x;
    st.current_y = to_y;
  }

  void
  HB_ALWAYS_INLINE
  cubic_to (void *draw_data, hb_draw_state_t &st,
	    float control1_x, float control1_y,
	    float control2_x, float control2_y,
	    float to_x, float to_y)
  {
    if (unlikely (!st.path_open)) start_path (draw_data, st);

    if (st.slant_xy)
    {
      control1_x += control1_y * st.slant_xy;
      control2_x += control2_y * st.slant_xy;
      to_x += to_y * st.slant_xy;
    }

    emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);

    st.current_x = to_x;
    st.current_y = to_y;
  }

  void
  HB_ALWAYS_INLINE
  close_path (void *draw_data, hb_draw_state_t &st)
  {
    if (likely (st.path_open))
    {
      if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
	emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
      emit_close_path (draw_data, st);
    }
    st.path_open = false;
    st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
  }

  protected:

  void start_path (void *draw_data, hb_draw_state_t &st)
  {
    assert (!st.path_open);
    emit_move_to (draw_data, st, st.current_x, st.current_y);
    st.path_open = true;
    st.path_start_x = st.current_x;
    st.path_start_y = st.current_y;
  }
};
DECLARE_NULL_INSTANCE (hb_draw_funcs_t);

struct hb_draw_session_t
{
  hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_xy = 0.f)
    : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
  { st.slant_xy = slant_xy; }

  ~hb_draw_session_t () { close_path (); }

  HB_ALWAYS_INLINE
  void move_to (float to_x, float to_y)
  {
    funcs->move_to (draw_data, st,
		    to_x, to_y);
  }
  HB_ALWAYS_INLINE
  void line_to (float to_x, float to_y)
  {
    funcs->line_to (draw_data, st,
		    to_x, to_y);
  }
  void
  HB_ALWAYS_INLINE
  quadratic_to (float control_x, float control_y,
		float to_x, float to_y)
  {
    funcs->quadratic_to (draw_data, st,
			 control_x, control_y,
			 to_x, to_y);
  }
  void
  HB_ALWAYS_INLINE
  cubic_to (float control1_x, float control1_y,
	    float control2_x, float control2_y,
	    float to_x, float to_y)
  {
    funcs->cubic_to (draw_data, st,
		     control1_x, control1_y,
		     control2_x, control2_y,
		     to_x, to_y);
  }
  HB_ALWAYS_INLINE
  void close_path ()
  {
    funcs->close_path (draw_data, st);
  }

  public:
  hb_draw_funcs_t *funcs;
  void *draw_data;
  hb_draw_state_t st;
};

#endif /* HB_DRAW_HH */
