Edit

kc3-lang/harfbuzz/src/hb-outline.cc

Branch :

  • Show log

    Commit

  • Author : Jason Simmons
    Date : 2023-03-13 18:24:39
    Hash : 32c889f1
    Message : Remove extra blank line in hb-outline.cc

  • src/hb-outline.cc
  • /*
     * Copyright © 2023  Behdad Esfahbod
     * Copyright © 1999  David Turner
     * Copyright © 2005  Werner Lemberg
     * Copyright © 2013-2015  Alexei Podtelezhnikov
     *
     *  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.
     */
    
    #include "hb.hh"
    
    #ifndef HB_NO_OUTLINE
    
    #include "hb-outline.hh"
    
    #include "hb-machinery.hh"
    
    
    void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
    {
      hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
    
      unsigned first = 0;
      for (unsigned contour : contours)
      {
        auto it = points.as_array ().sub_array (first, contour - first);
        while (it)
        {
          hb_outline_point_t p1 = *it++;
          switch (p1.type)
          {
    	case hb_outline_point_t::type_t::MOVE_TO:
    	{
    	  pen->move_to (pen_data, st,
    			   p1.x, p1.y);
    	}
    	break;
    	case hb_outline_point_t::type_t::LINE_TO:
    	{
    	  pen->line_to (pen_data, st,
    			   p1.x, p1.y);
    	}
    	break;
    	case hb_outline_point_t::type_t::QUADRATIC_TO:
    	{
    	  hb_outline_point_t p2 = *it++;
    	  pen->quadratic_to (pen_data, st,
    				p1.x, p1.y,
    				p2.x, p2.y);
    	}
    	break;
    	case hb_outline_point_t::type_t::CUBIC_TO:
    	{
    	  hb_outline_point_t p2 = *it++;
    	  hb_outline_point_t p3 = *it++;
    	  pen->cubic_to (pen_data, st,
    			    p1.x, p1.y,
    			    p2.x, p2.y,
    			    p3.x, p3.y);
    	}
    	break;
          }
        }
        pen->close_path (pen_data, st);
        first = contour;
      }
    }
    
    float hb_outline_t::control_area () const
    {
      float a = 0;
      unsigned first = 0;
      for (unsigned contour : contours)
      {
        for (unsigned i = first; i < contour; i++)
        {
          unsigned j = i + 1 < contour ? i + 1 : first;
    
          auto &pi = points[i];
          auto &pj = points[j];
          a += pi.x * pj.y - pi.y * pj.x;
        }
    
        first = contour;
      }
      return a * .5f;
    }
    
    void hb_outline_t::embolden (float x_strength, float y_strength,
    			     float x_shift, float y_shift)
    {
      /* This function is a straight port of FreeType's FT_Outline_EmboldenXY.
       * Permission has been obtained from the FreeType authors of the code
       * to relicense it under the HarfBuzz license. */
    
      if (!x_strength && !y_strength) return;
      if (!points) return;
    
      x_strength /= 2.f;
      y_strength /= 2.f;
    
      bool orientation_negative = control_area () < 0;
    
      signed first = 0;
      for (unsigned c = 0; c < contours.length; c++)
      {
        hb_outline_vector_t in, out, anchor, shift;
        float l_in, l_out, l_anchor = 0, l, q, d;
    
        l_in = 0;
        signed last = (int) contours[c] - 1;
    
        /* pacify compiler */
        in.x = in.y = anchor.x = anchor.y = 0;
    
        /* Counter j cycles though the points; counter i advances only  */
        /* when points are moved; anchor k marks the first moved point. */
        for ( signed i = last, j = first, k = -1;
    	  j != i && i != k;
    	  j = j < last ? j + 1 : first )
        {
          if ( j != k )
          {
    	out.x = points[j].x - points[i].x;
    	out.y = points[j].y - points[i].y;
    	l_out = out.normalize_len ();
    
    	if ( l_out == 0 )
    	  continue;
          }
          else
          {
    	out   = anchor;
    	l_out = l_anchor;
          }
    
          if ( l_in != 0 )
          {
    	if ( k < 0 )
    	{
    	  k        = i;
    	  anchor   = in;
    	  l_anchor = l_in;
    	}
    
    	d = in.x * out.x + in.y * out.y;
    
    	/* shift only if turn is less than ~160 degrees */
    	if ( d > -15.f/16.f )
    	{
    	  d = d + 1.f;
    
    	  /* shift components along lateral bisector in proper orientation */
    	  shift.x = in.y + out.y;
    	  shift.y = in.x + out.x;
    
    	  if ( orientation_negative )
    	    shift.x = -shift.x;
    	  else
    	    shift.y = -shift.y;
    
    	  /* restrict shift magnitude to better handle collapsing segments */
    	  q = out.x * in.y - out.y * in.x;
    	  if ( orientation_negative )
    	    q = -q;
    
    	  l = hb_min (l_in, l_out);
    
    	  /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
    	  if (x_strength * q <= l * d)
    	    shift.x = shift.x * x_strength / d;
    	  else
    	    shift.x = shift.x * l / q;
    
    
    	  if (y_strength * q <= l * d)
    	    shift.y = shift.y * y_strength / d;
    	  else
    	    shift.y = shift.y * l / q;
    	}
    	else
    	  shift.x = shift.y = 0;
    
    	for ( ;
    	      i != j;
    	      i = i < last ? i + 1 : first )
    	{
    	  points[i].x += x_shift + shift.x;
    	  points[i].y += y_shift + shift.y;
    	}
          }
          else
    	i = j;
    
          in   = out;
          l_in = l_out;
        }
    
        first = last + 1;
      }
    }
    
    static void
    hb_outline_recording_pen_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    				  void *data,
    				  hb_draw_state_t *st,
    				  float to_x, float to_y,
    				  void *user_data HB_UNUSED)
    {
      hb_outline_t *c = (hb_outline_t *) data;
    
      c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::MOVE_TO});
    }
    
    static void
    hb_outline_recording_pen_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    				  void *data,
    				  hb_draw_state_t *st,
    				  float to_x, float to_y,
    				  void *user_data HB_UNUSED)
    {
      hb_outline_t *c = (hb_outline_t *) data;
    
      c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::LINE_TO});
    }
    
    static void
    hb_outline_recording_pen_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    				       void *data,
    				       hb_draw_state_t *st,
    				       float control_x, float control_y,
    				       float to_x, float to_y,
    				       void *user_data HB_UNUSED)
    {
      hb_outline_t *c = (hb_outline_t *) data;
    
      c->points.push (hb_outline_point_t {control_x, control_y, hb_outline_point_t::type_t::QUADRATIC_TO});
      c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::QUADRATIC_TO});
    }
    
    static void
    hb_outline_recording_pen_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    				   void *data,
    				   hb_draw_state_t *st,
    				   float control1_x, float control1_y,
    				   float control2_x, float control2_y,
    				   float to_x, float to_y,
    				   void *user_data HB_UNUSED)
    {
      hb_outline_t *c = (hb_outline_t *) data;
    
      c->points.push (hb_outline_point_t {control1_x, control1_y, hb_outline_point_t::type_t::CUBIC_TO});
      c->points.push (hb_outline_point_t {control2_x, control2_y, hb_outline_point_t::type_t::CUBIC_TO});
      c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::CUBIC_TO});
    }
    
    static void
    hb_outline_recording_pen_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED,
    				     void *data,
    				     hb_draw_state_t *st,
    				     void *user_data HB_UNUSED)
    {
      hb_outline_t *c = (hb_outline_t *) data;
    
      c->contours.push (c->points.length);
    }
    
    static inline void free_static_outline_recording_pen_funcs ();
    
    static struct hb_outline_recording_pen_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_outline_recording_pen_funcs_lazy_loader_t>
    {
      static hb_draw_funcs_t *create ()
      {
        hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
    
        hb_draw_funcs_set_move_to_func (funcs, hb_outline_recording_pen_move_to, nullptr, nullptr);
        hb_draw_funcs_set_line_to_func (funcs, hb_outline_recording_pen_line_to, nullptr, nullptr);
        hb_draw_funcs_set_quadratic_to_func (funcs, hb_outline_recording_pen_quadratic_to, nullptr, nullptr);
        hb_draw_funcs_set_cubic_to_func (funcs, hb_outline_recording_pen_cubic_to, nullptr, nullptr);
        hb_draw_funcs_set_close_path_func (funcs, hb_outline_recording_pen_close_path, nullptr, nullptr);
    
        hb_draw_funcs_make_immutable (funcs);
    
        hb_atexit (free_static_outline_recording_pen_funcs);
    
        return funcs;
      }
    } static_outline_recording_pen_funcs;
    
    static inline
    void free_static_outline_recording_pen_funcs ()
    {
      static_outline_recording_pen_funcs.free_instance ();
    }
    
    hb_draw_funcs_t *
    hb_outline_recording_pen_get_funcs ()
    {
      return static_outline_recording_pen_funcs.get_unconst ();
    }
    
    
    #endif