Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / hb-draw.cc
index c0af6ce..f204f56 100644 (file)
 #include "hb.hh"
 
 #ifndef HB_NO_DRAW
-#ifdef HB_EXPERIMENTAL_API
 
 #include "hb-draw.hh"
-#include "hb-ot.h"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
 
 /**
- * hb_draw_funcs_set_move_to_func:
- * @funcs: draw functions object
- * @move_to: move-to callback
+ * SECTION:hb-draw
+ * @title: hb-draw
+ * @short_description: Glyph drawing
+ * @include: hb.h
  *
- * Sets move-to callback to the draw functions object.
+ * Functions for drawing (extracting) glyph shapes.
  *
- * Since: EXPERIMENTAL
+ * The #hb_draw_funcs_t struct can be used with hb_font_draw_glyph().
  **/
-void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t        *funcs,
-                               hb_draw_move_to_func_t  move_to)
+
+static void
+hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+                    hb_draw_state_t *st HB_UNUSED,
+                    float to_x HB_UNUSED, float to_y HB_UNUSED,
+                    void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+                    hb_draw_state_t *st HB_UNUSED,
+                    float to_x HB_UNUSED, float to_y HB_UNUSED,
+                    void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
+                         hb_draw_state_t *st,
+                         float control_x, float control_y,
+                         float to_x, float to_y,
+                         void *user_data HB_UNUSED)
+{
+#define HB_ONE_THIRD 0.33333333f
+  dfuncs->emit_cubic_to (draw_data, *st,
+                        (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
+                        (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
+                        (to_x + 2.f * control_x) * HB_ONE_THIRD,
+                        (to_y + 2.f * control_y) * HB_ONE_THIRD,
+                        to_x, to_y);
+#undef HB_ONE_THIRD
+}
+
+static void
+hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+                     hb_draw_state_t *st HB_UNUSED,
+                     float control1_x HB_UNUSED, float control1_y HB_UNUSED,
+                     float control2_x HB_UNUSED, float control2_y HB_UNUSED,
+                     float to_x HB_UNUSED, float to_y HB_UNUSED,
+                     void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+                       hb_draw_state_t *st HB_UNUSED,
+                       void *user_data HB_UNUSED) {}
+
+
+static bool
+_hb_draw_funcs_set_preamble (hb_draw_funcs_t    *dfuncs,
+                            bool                func_is_null,
+                            void              **user_data,
+                            hb_destroy_func_t  *destroy)
 {
-  if (unlikely (hb_object_is_immutable (funcs))) return;
-  funcs->move_to = move_to;
+  if (hb_object_is_immutable (dfuncs))
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    return false;
+  }
+
+  if (func_is_null)
+  {
+    if (*destroy)
+      (*destroy) (*user_data);
+    *destroy = nullptr;
+    *user_data = nullptr;
+  }
+
+  return true;
+}
+
+static bool
+_hb_draw_funcs_set_middle (hb_draw_funcs_t   *dfuncs,
+                          void              *user_data,
+                          hb_destroy_func_t  destroy)
+{
+  if (user_data && !dfuncs->user_data)
+  {
+    dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
+    if (unlikely (!dfuncs->user_data))
+      goto fail;
+  }
+  if (destroy && !dfuncs->destroy)
+  {
+    dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
+    if (unlikely (!dfuncs->destroy))
+      goto fail;
+  }
+
+  return true;
+
+fail:
+  if (destroy)
+    (destroy) (user_data);
+  return false;
+}
+
+#define HB_DRAW_FUNC_IMPLEMENT(name)                                           \
+                                                                               \
+void                                                                           \
+hb_draw_funcs_set_##name##_func (hb_draw_funcs_t        *dfuncs,               \
+                                hb_draw_##name##_func_t  func,                 \
+                                void                    *user_data,            \
+                                hb_destroy_func_t        destroy)              \
+{                                                                              \
+  if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
+      return;                                                            \
+                                                                               \
+  if (dfuncs->destroy && dfuncs->destroy->name)                                        \
+    dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
+                                                                        \
+  if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy))           \
+      return;                                                            \
+                                                                       \
+  if (func)                                                            \
+    dfuncs->func.name = func;                                          \
+  else                                                                 \
+    dfuncs->func.name = hb_draw_##name##_nil;                          \
+                                                                       \
+  if (dfuncs->user_data)                                               \
+    dfuncs->user_data->name = user_data;                               \
+  if (dfuncs->destroy)                                                 \
+    dfuncs->destroy->name = destroy;                                   \
 }
 
+HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
 /**
- * hb_draw_funcs_set_line_to_func:
- * @funcs: draw functions object
- * @line_to: line-to callback
+ * hb_draw_funcs_create:
+ *
+ * Creates a new draw callbacks object.
  *
- * Sets line-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
+ * reference count should be released with hb_draw_funcs_destroy when you are
+ * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
+ * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
+ * be returned.
  *
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
-void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t        *funcs,
-                               hb_draw_line_to_func_t  line_to)
+hb_draw_funcs_t *
+hb_draw_funcs_create ()
 {
-  if (unlikely (hb_object_is_immutable (funcs))) return;
-  funcs->line_to = line_to;
+  hb_draw_funcs_t *dfuncs;
+  if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
+    return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+
+  dfuncs->func =  Null (hb_draw_funcs_t).func;
+
+  return dfuncs;
 }
 
+DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
+    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+  }
+};
+
 /**
- * hb_draw_funcs_set_quadratic_to_func:
- * @funcs: draw functions object
- * @move_to: quadratic-to callback
+ * hb_draw_funcs_get_empty:
  *
- * Sets quadratic-to callback to the draw functions object.
+ * Fetches the singleton empty draw-functions structure.
  *
- * Since: EXPERIMENTAL
+ * Return value: (transfer full): The empty draw-functions structure
+ *
+ * Since: 7.0.0
  **/
-void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t             *funcs,
-                                    hb_draw_quadratic_to_func_t  quadratic_to)
+hb_draw_funcs_t *
+hb_draw_funcs_get_empty ()
 {
-  if (unlikely (hb_object_is_immutable (funcs))) return;
-  funcs->quadratic_to = quadratic_to;
-  funcs->is_quadratic_to_set = true;
+  return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
 }
 
 /**
- * hb_draw_funcs_set_cubic_to_func:
- * @funcs: draw functions
- * @cubic_to: cubic-to callback
+ * hb_draw_funcs_reference: (skip)
+ * @dfuncs: draw functions
+ *
+ * Increases the reference count on @dfuncs by one.
  *
- * Sets cubic-to callback to the draw functions object.
+ * This prevents @dfuncs from being destroyed until a matching
+ * call to hb_draw_funcs_destroy() is made.
  *
- * Since: EXPERIMENTAL
+ * Return value: (transfer full):
+ * The referenced #hb_draw_funcs_t.
+ *
+ * Since: 4.0.0
  **/
-void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t         *funcs,
-                                hb_draw_cubic_to_func_t  cubic_to)
+hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
 {
-  if (unlikely (hb_object_is_immutable (funcs))) return;
-  funcs->cubic_to = cubic_to;
+  return hb_object_reference (dfuncs);
 }
 
 /**
- * hb_draw_funcs_set_close_path_func:
- * @funcs: draw functions object
- * @close_path: close-path callback
+ * hb_draw_funcs_destroy: (skip)
+ * @dfuncs: draw functions
  *
- * Sets close-path callback to the draw functions object.
+ * Deallocate the @dfuncs.
+ * Decreases the reference count on @dfuncs by one. If the result is zero, then
+ * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
  *
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
 void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t           *funcs,
-                                  hb_draw_close_path_func_t  close_path)
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
 {
-  if (unlikely (hb_object_is_immutable (funcs))) return;
-  funcs->close_path = close_path;
-}
+  if (!hb_object_destroy (dfuncs)) return;
 
-static void
-_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
+  if (dfuncs->destroy)
+  {
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+    if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
+      HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+  }
 
-static void
-_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
+  hb_free (dfuncs->destroy);
+  hb_free (dfuncs->user_data);
 
-static void
-_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
-                  hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
-                  void *user_data HB_UNUSED) {}
+  hb_free (dfuncs);
+}
 
-static void
-_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
-              hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
-              hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
-              void *user_data HB_UNUSED) {}
+/**
+ * hb_draw_funcs_set_user_data: (skip)
+ * @dfuncs: The draw-functions structure
+ * @key: The user-data key
+ * @data: A pointer to the user data
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
+ * @replace: Whether to replace an existing data with the same key
+ *
+ * Attaches a user-data key/data pair to the specified draw-functions structure. 
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 7.0.0
+ **/
+hb_bool_t
+hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
+                            hb_user_data_key_t *key,
+                            void *              data,
+                            hb_destroy_func_t   destroy,
+                            hb_bool_t           replace)
+{
+  return hb_object_set_user_data (dfuncs, key, data, destroy, replace);
+}
 
-static void
-_close_path_nil (void *user_data HB_UNUSED) {}
+/**
+ * hb_draw_funcs_get_user_data: (skip)
+ * @dfuncs: The draw-functions structure
+ * @key: The user-data key to query
+ *
+ * Fetches the user-data associated with the specified key,
+ * attached to the specified draw-functions structure.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 7.0.0
+ **/
+void *
+hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
+                            hb_user_data_key_t       *key)
+{
+  return hb_object_get_user_data (dfuncs, key);
+}
 
 /**
- * hb_draw_funcs_create:
+ * hb_draw_funcs_make_immutable:
+ * @dfuncs: draw functions
  *
- * Creates a new draw callbacks object.
+ * Makes @dfuncs object immutable.
  *
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
-hb_draw_funcs_t *
-hb_draw_funcs_create ()
+void
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
 {
-  hb_draw_funcs_t *funcs;
-  if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
-    return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+  if (hb_object_is_immutable (dfuncs))
+    return;
 
-  funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
-  funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
-  funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
-  funcs->is_quadratic_to_set = false;
-  funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
-  funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
-  return funcs;
+  hb_object_make_immutable (dfuncs);
 }
 
 /**
- * hb_draw_funcs_reference:
- * @funcs: draw functions
+ * hb_draw_funcs_is_immutable:
+ * @dfuncs: draw functions
+ *
+ * Checks whether @dfuncs is immutable.
  *
- * Add to callbacks object refcount.
+ * Return value: `true` if @dfuncs is immutable, `false` otherwise
  *
- * Returns: The same object.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
-hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
+hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
 {
-  return hb_object_reference (funcs);
+  return hb_object_is_immutable (dfuncs);
 }
 
+
 /**
- * hb_draw_funcs_destroy:
- * @funcs: draw functions
+ * hb_draw_move_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
  *
- * Decreases refcount of callbacks object and deletes the object if it reaches
- * to zero.
+ * Perform a "move-to" draw operation.
  *
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
 void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+                hb_draw_state_t *st,
+                float to_x, float to_y)
 {
-  if (!hb_object_destroy (funcs)) return;
-
-  hb_free (funcs);
+  dfuncs->move_to (draw_data, *st,
+                  to_x, to_y);
 }
 
 /**
- * hb_draw_funcs_make_immutable:
- * @funcs: draw functions
+ * hb_draw_line_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
  *
- * Makes funcs object immutable.
+ * Perform a "line-to" draw operation.
  *
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
 void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+                hb_draw_state_t *st,
+                float to_x, float to_y)
 {
-  if (hb_object_is_immutable (funcs))
-    return;
-
-  hb_object_make_immutable (funcs);
+  dfuncs->line_to (draw_data, *st,
+                  to_x, to_y);
 }
 
 /**
- * hb_draw_funcs_is_immutable:
- * @funcs: draw functions
+ * hb_draw_quadratic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
  *
- * Checks whether funcs is immutable.
+ * Perform a "quadratic-to" draw operation.
  *
- * Returns: If is immutable.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
-hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
+void
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+                     hb_draw_state_t *st,
+                     float control_x, float control_y,
+                     float to_x, float to_y)
 {
-  return hb_object_is_immutable (funcs);
+  dfuncs->quadratic_to (draw_data, *st,
+                       control_x, control_y,
+                       to_x, to_y);
 }
 
 /**
- * hb_font_draw_glyph:
- * @font: a font object
- * @glyph: a glyph id
- * @funcs: draw callbacks object
- * @user_data: parameter you like be passed to the callbacks when are called
+ * hb_draw_cubic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
  *
- * Draw a glyph.
+ * Perform a "cubic-to" draw operation.
  *
- * Returns: Whether the font had the glyph and the operation completed successfully.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
  **/
-hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
-                   const hb_draw_funcs_t *funcs,
-                   void *user_data)
+void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, 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 (funcs == &Null (hb_draw_funcs_t) ||
-               glyph >= font->face->get_num_glyphs ()))
-    return false;
-
-  draw_helper_t draw_helper (funcs, user_data);
-  if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
-#ifndef HB_NO_CFF
-  if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
-  if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
-#endif
+  dfuncs->cubic_to (draw_data, *st,
+                   control1_x, control1_y,
+                   control2_x, control2_y,
+                   to_x, to_y);
+}
 
-  return false;
+/**
+ * hb_draw_close_path:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ *
+ * Perform a "close-path" draw operation.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+                   hb_draw_state_t *st)
+{
+  dfuncs->close_path (draw_data, *st);
 }
 
-#endif
+
 #endif