text:
/*
 * Copyright © 2011,2012  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#include "hb.hh"

#ifndef HB_NO_OT_SHAPE

#include "hb-ot-shape-fallback.hh"
#include "hb-kern.hh"

static unsigned int
recategorize_combining_class (hb_codepoint_t u,
			      unsigned int klass)
{
  if (klass >= 200)
    return klass;

  /* Thai / Lao need some per-character work. */
  if ((u & ~0xFF) == 0x0E00u)
  {
    if (unlikely (klass == 0))
    {
      switch (u)
      {
	case 0x0E31u:
	case 0x0E34u:
	case 0x0E35u:
	case 0x0E36u:
	case 0x0E37u:
	case 0x0E47u:
	case 0x0E4Cu:
	case 0x0E4Du:
	case 0x0E4Eu:
	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
	  break;

	case 0x0EB1u:
	case 0x0EB4u:
	case 0x0EB5u:
	case 0x0EB6u:
	case 0x0EB7u:
	case 0x0EBBu:
	case 0x0ECCu:
	case 0x0ECDu:
	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
	  break;

	case 0x0EBCu:
	  klass = HB_UNICODE_COMBINING_CLASS_BELOW;
	  break;
      }
    } else {
      /* Thai virama is below-right */
      if (u == 0x0E3Au)
	klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
    }
  }

  switch (klass)
  {

    /* Hebrew */

    case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
    case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
    case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
    case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
    case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
    case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
    case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
    case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
    case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
    case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
      return HB_UNICODE_COMBINING_CLASS_BELOW;

    case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
      return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;

    case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;

    case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
      return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;

    case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
      return HB_UNICODE_COMBINING_CLASS_ABOVE;

    case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
      break;

    /* Arabic and Syriac */

    case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
    case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
    case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
    case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
    case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
    case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
    case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
    case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
      return HB_UNICODE_COMBINING_CLASS_ABOVE;

    case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
    case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
      return HB_UNICODE_COMBINING_CLASS_BELOW;

    /* Thai */

    case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
      return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;

    case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;

    /* Lao */

    case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
      return HB_UNICODE_COMBINING_CLASS_BELOW;

    case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
      return HB_UNICODE_COMBINING_CLASS_ABOVE;

    /* Tibetan */

    case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
      return HB_UNICODE_COMBINING_CLASS_BELOW;

    case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
      return HB_UNICODE_COMBINING_CLASS_ABOVE;

    case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
      return HB_UNICODE_COMBINING_CLASS_BELOW;

  }

  return klass;
}

void
_hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
							hb_font_t *font HB_UNUSED,
							hb_buffer_t  *buffer)
{
#ifdef HB_NO_OT_SHAPE_FALLBACK
  return;
#endif

  unsigned int count = buffer->len;
  hb_glyph_info_t *info = buffer->info;
  for (unsigned int i = 0; i < count; i++)
    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
      unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
      combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
      _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
    }
}

static void
zero_mark_advances (hb_buffer_t *buffer,
		    unsigned int start,
		    unsigned int end,
		    bool adjust_offsets_when_zeroing)
{
  hb_glyph_info_t *info = buffer->info;
  for (unsigned int i = start; i < end; i++)
    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
    {
      if (adjust_offsets_when_zeroing)
      {
	buffer->pos[i].x_offset -= buffer->pos[i].x_advance;
	buffer->pos[i].y_offset -= buffer->pos[i].y_advance;
      }
      buffer->pos[i].x_advance = 0;
      buffer->pos[i].y_advance = 0;
    }
}

static inline void
position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED,
	       hb_font_t *font,
	       hb_buffer_t  *buffer,
	       hb_glyph_extents_t &base_extents,
	       unsigned int i,
	       unsigned int combining_class)
{
  hb_glyph_extents_t mark_extents;
  if (!font->get_glyph_extents (buffer->info[i].codepoint, &mark_extents))
    return;

  hb_position_t y_gap = font->y_scale / 16;

  hb_glyph_position_t &pos = buffer->pos[i];
  pos.x_offset = pos.y_offset = 0;

  /* We don't position LEFT and RIGHT marks. */

  /* X positioning */
  switch (combining_class)
  {
    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
      if (buffer->props.direction == HB_DIRECTION_LTR) {
	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
	break;
      } else if (buffer->props.direction == HB_DIRECTION_RTL) {
	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
	break;
      }
      HB_FALLTHROUGH;

    default:
    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
    case HB_UNICODE_COMBINING_CLASS_BELOW:
    case HB_UNICODE_COMBINING_CLASS_ABOVE:
      /* Center align. */
      pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
      break;

    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
      /* Left align. */
      pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
      break;

    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
      /* Right align. */
      pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
      break;
  }

  /* Y positioning */
  switch (combining_class)
  {
    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
    case HB_UNICODE_COMBINING_CLASS_BELOW:
    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
      /* Add gap, fall-through. */
      base_extents.height -= y_gap;
      HB_FALLTHROUGH;

    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
      pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
      /* Never shift up "below" marks. */
      if ((y_gap > 0) == (pos.y_offset > 0))
      {
	base_extents.height -= pos.y_offset;
	pos.y_offset = 0;
      }
      base_extents.height += mark_extents.height;
      break;

    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
    case HB_UNICODE_COMBINING_CLASS_ABOVE:
    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
      /* Add gap, fall-through. */
      base_extents.y_bearing += y_gap;
      base_extents.height -= y_gap;
      HB_FALLTHROUGH;

    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
      pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
      /* Don't shift down "above" marks too much. */
      if ((y_gap > 0) != (pos.y_offset > 0))
      {
	unsigned int correction = -pos.y_offset / 2;
	base_extents.y_bearing += correction;
	base_extents.height -= correction;
	pos.y_offset += correction;
      }
      base_extents.y_bearing -= mark_extents.height;
      base_extents.height += mark_extents.height;
      break;
  }
}

static inline void
position_around_base (const hb_ot_shape_plan_t *plan,
		      hb_font_t *font,
		      hb_buffer_t  *buffer,
		      unsigned int base,
		      unsigned int end,
		      bool adjust_offsets_when_zeroing)
{
  hb_direction_t horiz_dir = HB_DIRECTION_INVALID;

  buffer->unsafe_to_break (base, end);

  hb_glyph_extents_t base_extents;
  if (!font->get_glyph_extents (buffer->info[base].codepoint,
				&base_extents))
  {
    /* If extents don't work, zero marks and go home. */
    zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
    return;
  }
  base_extents.y_bearing += buffer->pos[base].y_offset;
  /* Use horizontal advance for horizontal positioning.
   * Generally a better idea.  Also works for zero-ink glyphs.  See:
   * https://github.com/harfbuzz/harfbuzz/issues/1532 */
  base_extents.x_bearing = 0;
  base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint);

  unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
  /* Use integer for num_lig_components such that it doesn't convert to unsigned
   * when we divide or multiply by it. */
  int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);

  hb_position_t x_offset = 0, y_offset = 0;
  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
    x_offset -= buffer->pos[base].x_advance;
    y_offset -= buffer->pos[base].y_advance;
  }

  hb_glyph_extents_t component_extents = base_extents;
  int last_lig_component = -1;
  unsigned int last_combining_class = 255;
  hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
  hb_glyph_info_t *info = buffer->info;
  for (unsigned int i = base + 1; i < end; i++)
    if (_hb_glyph_info_get_modified_combining_class (&info[i]))
    {
      if (num_lig_components > 1) {
	unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
	int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
	/* Conditions for attaching to the last component. */
	if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
	  this_lig_component = num_lig_components - 1;
	if (last_lig_component != this_lig_component)
	{
	  last_lig_component = this_lig_component;
	  last_combining_class = 255;
	  component_extents = base_extents;
	  if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) {
	    if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction))
	      horiz_dir = plan->props.direction;
	    else
	      horiz_dir = hb_script_get_horizontal_direction (plan->props.script);
	  }
	  if (horiz_dir == HB_DIRECTION_LTR)
	    component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components;
	  else
	    component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components;
	  component_extents.width /= num_lig_components;
	}
      }

      unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
      if (last_combining_class != this_combining_class)
      {
	last_combining_class = this_combining_class;
	cluster_extents = component_extents;
      }

      position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);

      buffer->pos[i].x_advance = 0;
      buffer->pos[i].y_advance = 0;
      buffer->pos[i].x_offset += x_offset;
      buffer->pos[i].y_offset += y_offset;

    } else {
      if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
	x_offset -= buffer->pos[i].x_advance;
	y_offset -= buffer->pos[i].y_advance;
      } else {
	x_offset += buffer->pos[i].x_advance;
	y_offset += buffer->pos[i].y_advance;
      }
    }
}

static inline void
position_cluster (const hb_ot_shape_plan_t *plan,
		  hb_font_t *font,
		  hb_buffer_t  *buffer,
		  unsigned int start,
		  unsigned int end,
		  bool adjust_offsets_when_zeroing)
{
  if (end - start < 2)
    return;

  /* Find the base glyph */
  hb_glyph_info_t *info = buffer->info;
  for (unsigned int i = start; i < end; i++)
    if (!_hb_glyph_info_is_unicode_mark (&info[i]))
    {
      /* Find mark glyphs */
      unsigned int j;
      for (j = i + 1; j < end; j++)
	if (!_hb_glyph_info_is_unicode_mark (&info[j]))
	  break;

      position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);

      i = j - 1;
    }
}

void
_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
				     hb_font_t *font,
				     hb_buffer_t  *buffer,
				     bool adjust_offsets_when_zeroing)
{
#ifdef HB_NO_OT_SHAPE_FALLBACK
  return;
#endif

  _hb_buffer_assert_gsubgpos_vars (buffer);

  unsigned int start = 0;
  unsigned int count = buffer->len;
  hb_glyph_info_t *info = buffer->info;
  for (unsigned int i = 1; i < count; i++)
    if (likely (!_hb_glyph_info_is_unicode_mark (&info[i]))) {
      position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
      start = i;
    }
  position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
}

#ifndef HB_DISABLE_DEPRECATED
struct hb_ot_shape_fallback_kern_driver_t
{
  hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
				      hb_buffer_t *buffer) :
    font (font_), direction (buffer->props.direction) {}

  hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
  {
    hb_position_t kern = 0;
    font->get_glyph_kerning_for_direction (first, second,
					   direction,
					   &kern, &kern);
    return kern;
  }

  hb_font_t *font;
  hb_direction_t direction;
};
#endif

/* Performs font-assisted kerning. */
void
_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
			    hb_font_t *font,
			    hb_buffer_t *buffer)
{
#ifdef HB_NO_OT_SHAPE_FALLBACK
  return;
#endif

#ifndef HB_DISABLE_DEPRECATED
  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
      !font->has_glyph_h_kerning_func () :
      !font->has_glyph_v_kerning_func ())
    return;

  bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);

  if (reverse)
    buffer->reverse ();

  hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
  OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
  machine.kern (font, buffer, plan->kern_mask, false);

  if (reverse)
    buffer->reverse ();
#endif
}

/* Adjusts width of various spaces. */
void
_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
			      hb_font_t *font,
			      hb_buffer_t  *buffer)
{
  hb_glyph_info_t *info = buffer->info;
  hb_glyph_position_t *pos = buffer->pos;
  bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
  unsigned int count = buffer->len;
  for (unsigned int i = 0; i < count; i++)
    if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
    {
      hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
      hb_codepoint_t glyph;
      typedef hb_unicode_funcs_t t;
      switch (space_type)
      {
	case t::NOT_SPACE: /* Shouldn't happen. */
	case t::SPACE:
	  break;

	case t::SPACE_EM:
	case t::SPACE_EM_2:
	case t::SPACE_EM_3:
	case t::SPACE_EM_4:
	case t::SPACE_EM_5:
	case t::SPACE_EM_6:
	case t::SPACE_EM_16:
	  if (horizontal)
	    pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type;
	  else
	    pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type;
	  break;

	case t::SPACE_4_EM_18:
	  if (horizontal)
	    pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18;
	  else
	    pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18;
	  break;

	case t::SPACE_FIGURE:
	  for (char u = '0'; u <= '9'; u++)
	    if (font->get_nominal_glyph (u, &glyph))
	    {
	      if (horizontal)
		pos[i].x_advance = font->get_glyph_h_advance (glyph);
	      else
		pos[i].y_advance = font->get_glyph_v_advance (glyph);
	      break;
	    }
	  break;

	case t::SPACE_PUNCTUATION:
	  if (font->get_nominal_glyph ('.', &glyph) ||
	      font->get_nominal_glyph (',', &glyph))
	  {
	    if (horizontal)
	      pos[i].x_advance = font->get_glyph_h_advance (glyph);
	    else
	      pos[i].y_advance = font->get_glyph_v_advance (glyph);
	  }
	  break;

	case t::SPACE_NARROW:
	  /* Half-space?
	   * Unicode doc https://unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
	   * However, in my testing, many fonts have their regular space being about that
	   * size.  To me, a percentage of the space width makes more sense.  Half is as
	   * good as any. */
	  if (horizontal)
	    pos[i].x_advance /= 2;
	  else
	    pos[i].y_advance /= 2;
	  break;
      }
    }
}

#endif


text:
#line 1 "hb-buffer-deserialize-json.rl"
/*
 * Copyright © 2013  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_BUFFER_DESERIALIZE_JSON_HH
#define HB_BUFFER_DESERIALIZE_JSON_HH

#include "hb.hh"

#line 36 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
	0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
	48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
	9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
	120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
	9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
	65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
};

static const char _deserialize_json_key_spans[] = {
	0, 115, 26, 7, 2, 1, 50, 49,
	10, 117, 117, 117, 1, 50, 49, 10,
	117, 117, 1, 1, 50, 49, 117, 117,
	2, 1, 50, 49, 10, 117, 117, 1,
	50, 49, 10, 117, 117, 1, 50, 49,
	58, 89, 117, 117, 85, 115, 0
};

static const short _deserialize_json_index_offsets[] = {
	0, 0, 116, 143, 151, 154, 156, 207,
	257, 268, 386, 504, 622, 624, 675, 725,
	736, 854, 972, 974, 976, 1027, 1077, 1195,
	1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666,
	1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069,
	2119, 2178, 2268, 2386, 2504, 2590, 2706
};

static const char _deserialize_json_indicies[] = {
	0, 0, 0, 0, 0, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	0, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 2, 1, 3, 3, 3,
	3, 3, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 3, 1, 4, 1,
	5, 1, 6, 7, 1, 1, 8, 1,
	9, 10, 1, 11, 1, 11, 11, 11,
	11, 11, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 11, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 12, 1,
	12, 12, 12, 12, 12, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 12,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 13, 1, 1, 14,
	15, 15, 15, 15, 15, 15, 15, 15,
	15, 1, 16, 17, 17, 17, 17, 17,
	17, 17, 17, 17, 1, 18, 18, 18,
	18, 18, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 18, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	19, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 20, 1, 21, 21, 21, 21, 21,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 21, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 3, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 22,
	1, 18, 18, 18, 18, 18, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	18, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 19, 1, 1, 1,
	17, 17, 17, 17, 17, 17, 17, 17,
	17, 17, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 20, 1, 23,
	1, 23, 23, 23, 23, 23, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	23, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 24, 1, 24, 24, 24, 24,
	24, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 24, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	25, 1, 1, 26, 27, 27, 27, 27,
	27, 27, 27, 27, 27, 1, 28, 29,
	29, 29, 29, 29, 29, 29, 29, 29,
	1, 30, 30, 30, 30, 30, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	30, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 31, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 32, 1, 30,
	30, 30, 30, 30, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 30, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 31, 1, 1, 1, 29, 29,
	29, 29, 29, 29, 29, 29, 29, 29,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 32, 1, 33, 1, 34,
	1, 34, 34, 34, 34, 34, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	34, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 35, 1, 35, 35, 35, 35,
	35, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 35, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 36, 37, 37, 37, 37,
	37, 37, 37, 37, 37, 1, 38, 38,
	38, 38, 38, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 38, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 39, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 40, 1, 38, 38, 38, 38,
	38, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 38, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 39,
	1, 1, 1, 41, 41, 41, 41, 41,
	41, 41, 41, 41, 41, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	40, 1, 42, 43, 1, 44, 1, 44,
	44, 44, 44, 44, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 44, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	45, 1, 45, 45, 45, 45, 45, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 45, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 46, 1,
	1, 47, 48, 48, 48, 48, 48, 48,
	48, 48, 48, 1, 49, 50, 50, 50,
	50, 50, 50, 50, 50, 50, 1, 51,
	51, 51, 51, 51, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 51, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 52, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 53, 1, 51, 51, 51,
	51, 51, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 51, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	52, 1, 1, 1, 50, 50, 50, 50,
	50, 50, 50, 50, 50, 50, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 53, 1, 54, 1, 54, 54, 54,
	54, 54, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 54, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 55, 1,
	55, 55, 55, 55, 55, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 55,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 56, 1, 1, 57,
	58, 58, 58, 58, 58, 58, 58, 58,
	58, 1, 59, 60, 60, 60, 60, 60,
	60, 60, 60, 60, 1, 61, 61, 61,
	61, 61, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 61, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	62, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 63, 1, 61, 61, 61, 61, 61,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 61, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 62, 1,
	1, 1, 60, 60, 60, 60, 60, 60,
	60, 60, 60, 60, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 63,
	1, 64, 1, 64, 64, 64, 64, 64,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 64, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 65, 1, 65, 65,
	65, 65, 65, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 65, 1, 66,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 67, 68, 68,
	68, 68, 68, 68, 68, 68, 68, 1,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 1, 1, 1, 1, 1, 1,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 69, 69, 69, 69, 69, 69,
	69, 69, 1, 70, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 71, 71,
	1, 71, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 1, 1, 1, 1, 1,
	1, 1, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 1, 1, 1, 1,
	71, 1, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 71, 71, 71, 71,
	71, 71, 71, 71, 1, 72, 72, 72,
	72, 72, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 72, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	73, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 74, 1, 72, 72, 72, 72, 72,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 72, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 73, 1,
	1, 1, 75, 75, 75, 75, 75, 75,
	75, 75, 75, 75, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 74,
	1, 76, 76, 76, 76, 76, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	76, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 77, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 78, 1, 0,
	0, 0, 0, 0, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 0, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1,
	1, 2, 1, 1, 0
};

static const char _deserialize_json_trans_targs[] = {
	1, 0, 2, 2, 3, 4, 18, 24,
	37, 5, 12, 6, 7, 8, 9, 11,
	9, 11, 10, 2, 44, 10, 44, 13,
	14, 15, 16, 17, 16, 17, 10, 2,
	44, 19, 20, 21, 22, 23, 10, 2,
	44, 23, 25, 31, 26, 27, 28, 29,
	30, 29, 30, 10, 2, 44, 32, 33,
	34, 35, 36, 35, 36, 10, 2, 44,
	38, 39, 40, 42, 43, 41, 10, 41,
	10, 2, 44, 43, 44, 45, 46
};

static const char _deserialize_json_trans_actions[] = {
	0, 0, 1, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 2, 2, 2,
	0, 0, 3, 3, 4, 0, 5, 0,
	0, 2, 2, 2, 0, 0, 6, 6,
	7, 0, 0, 0, 2, 2, 8, 8,
	9, 0, 0, 0, 0, 0, 2, 2,
	2, 0, 0, 10, 10, 11, 0, 0,
	2, 2, 2, 0, 0, 12, 12, 13,
	0, 0, 0, 2, 2, 2, 14, 0,
	15, 15, 16, 0, 0, 0, 0
};

static const int deserialize_json_start = 1;
static const int deserialize_json_first_final = 44;
static const int deserialize_json_error = 0;

static const int deserialize_json_en_main = 1;

#line 97 "hb-buffer-deserialize-json.rl"

static hb_bool_t
_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
				    const char *buf,
				    unsigned int buf_len,
				    const char **end_ptr,
				    hb_font_t *font)
{
  const char *p = buf, *pe = buf + buf_len;

  /* Ensure we have positions. */
  (void) hb_buffer_get_glyph_positions (buffer, nullptr);

  while (p < pe && ISSPACE (*p))
    p++;
  if (p < pe && *p == (buffer->len ? ',' : '['))
  {
    *end_ptr = ++p;
  }

  const char *tok = nullptr;
  int cs;
  hb_glyph_info_t info = {0};
  hb_glyph_position_t pos = {0};

#line 466 "hb-buffer-deserialize-json.hh"
	{
	cs = deserialize_json_start;
	}

#line 471 "hb-buffer-deserialize-json.hh"
	{
	int _slen;
	int _trans;
	const unsigned char *_keys;
	const char *_inds;
	if ( p == pe )
		goto _test_eof;
	if ( cs == 0 )
		goto _out;
_resume:
	_keys = _deserialize_json_trans_keys + (cs<<1);
	_inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs];

	_slen = _deserialize_json_key_spans[cs];
	_trans = _inds[ _slen > 0 && _keys[0] <=(*p) &&
		(*p) <= _keys[1] ?
		(*p) - _keys[0] : _slen ];

	cs = _deserialize_json_trans_targs[_trans];

	if ( _deserialize_json_trans_actions[_trans] == 0 )
		goto _again;

	switch ( _deserialize_json_trans_actions[_trans] ) {
	case 1:
#line 38 "hb-buffer-deserialize-json.rl"
	{
	memset (&info, 0, sizeof (info));
	memset (&pos , 0, sizeof (pos ));
}
	break;
	case 5:
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 2:
#line 51 "hb-buffer-deserialize-json.rl"
	{
	tok = p;
}
	break;
	case 14:
#line 55 "hb-buffer-deserialize-json.rl"
	{
	if (!hb_font_glyph_from_string (font,
					tok, p - tok,
					&info.codepoint))
	  return false;
}
	break;
	case 15:
#line 62 "hb-buffer-deserialize-json.rl"
	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
	break;
	case 8:
#line 63 "hb-buffer-deserialize-json.rl"
	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
	break;
	case 10:
#line 64 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
	break;
	case 12:
#line 65 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
	break;
	case 3:
#line 66 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
	break;
	case 6:
#line 67 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
	break;
	case 16:
#line 62 "hb-buffer-deserialize-json.rl"
	{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 9:
#line 63 "hb-buffer-deserialize-json.rl"
	{ if (!parse_uint (tok, p, &info.cluster )) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 11:
#line 64 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.x_offset )) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 13:
#line 65 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.y_offset )) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 4:
#line 66 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
	case 7:
#line 67 "hb-buffer-deserialize-json.rl"
	{ if (!parse_int  (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
	{
	buffer->add_info (info);
	if (unlikely (!buffer->successful))
	  return false;
	buffer->pos[buffer->len - 1] = pos;
	*end_ptr = p;
}
	break;
#line 624 "hb-buffer-deserialize-json.hh"
	}

_again:
	if ( cs == 0 )
		goto _out;
	if ( ++p != pe )
		goto _resume;
	_test_eof: {}
	_out: {}
	}

#line 125 "hb-buffer-deserialize-json.rl"

  *end_ptr = p;

  return p == pe && *(p-1) != ']';
}

#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */

repo_language: C

mime_type: text/x-c


text:
/*
 * Copyright © 2017  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_OT_VAR_AVAR_TABLE_HH
#define HB_OT_VAR_AVAR_TABLE_HH

#include "hb-open-type.hh"

/*
 * avar -- Axis Variations
 * https://docs.microsoft.com/en-us/typography/opentype/spec/avar
 */

#define HB_OT_TAG_avar HB_TAG('a','v','a','r')

namespace OT {

struct AxisValueMap
{
  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  public:
  F2DOT14	coords[2];
//   F2DOT14	fromCoord;	/* A normalized coordinate value obtained using
//				 * default normalization. */
//   F2DOT14	toCoord;	/* The modified, normalized coordinate value. */

  public:
  DEFINE_SIZE_STATIC (4);
};

struct SegmentMaps : ArrayOf<AxisValueMap>
{
  int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
  {
#define fromCoord coords[from_offset]
#define toCoord coords[to_offset]
    /* The following special-cases are not part of OpenType, which requires
     * that at least -1, 0, and +1 must be mapped. But we include these as
     * part of a better error recovery scheme. */
    if (len < 2)
    {
      if (!len)
	return value;
      else /* len == 1*/
	return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
    }

    if (value <= arrayZ[0].fromCoord)
      return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;

    unsigned int i;
    unsigned int count = len - 1;
    for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
      ;

    if (value >= arrayZ[i].fromCoord)
      return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;

    if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
      return arrayZ[i-1].toCoord;

    int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
    return roundf (arrayZ[i-1].toCoord + ((float) (arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
					  (value - arrayZ[i-1].fromCoord)) / denom);
#undef toCoord
#undef fromCoord
  }

  int unmap (int value) const { return map (value, 1, 0); }

  public:
  DEFINE_SIZE_ARRAY (2, *this);
};

struct avar
{
  static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!(version.sanitize (c) &&
		    version.major == 1 &&
		    c->check_struct (this))))
      return_trace (false);

    const SegmentMaps *map = &firstAxisSegmentMaps;
    unsigned int count = axisCount;
    for (unsigned int i = 0; i < count; i++)
    {
      if (unlikely (!map->sanitize (c)))
	return_trace (false);
      map = &StructAfter<SegmentMaps> (*map);
    }

    return_trace (true);
  }

  void map_coords (int *coords, unsigned int coords_length) const
  {
    unsigned int count = hb_min (coords_length, axisCount);

    const SegmentMaps *map = &firstAxisSegmentMaps;
    for (unsigned int i = 0; i < count; i++)
    {
      coords[i] = map->map (coords[i]);
      map = &StructAfter<SegmentMaps> (*map);
    }
  }

  void unmap_coords (int *coords, unsigned int coords_length) const
  {
    unsigned int count = hb_min (coords_length, axisCount);

    const SegmentMaps *map = &firstAxisSegmentMaps;
    for (unsigned int i = 0; i < count; i++)
    {
      coords[i] = map->unmap (coords[i]);
      map = &StructAfter<SegmentMaps> (*map);
    }
  }

  protected:
  FixedVersion<>version;	/* Version of the avar table
				 * initially set to 0x00010000u */
  HBUINT16	reserved;	/* This field is permanently reserved. Set to 0. */
  HBUINT16	axisCount;	/* The number of variation axes in the font. This
				 * must be the same number as axisCount in the
				 * 'fvar' table. */
  SegmentMaps	firstAxisSegmentMaps;

  public:
  DEFINE_SIZE_MIN (8);
};

} /* namespace OT */

#endif /* HB_OT_VAR_AVAR_TABLE_HH */


text:
/*
 * Copyright © 2007,2008,2009  Red Hat, Inc.
 * Copyright © 2012,2013  Google, Inc.
 *
 *  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.
 *
 * Red Hat Author(s): Behdad Esfahbod
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_OT_FACE_HH
#define HB_OT_FACE_HH

#include "hb.hh"

#include "hb-machinery.hh"

/*
 * hb_ot_face_t
 */

/* Declare tables. */
#define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
#undef HB_OT_TABLE

struct hb_ot_face_t
{
  HB_INTERNAL void init0 (hb_face_t *face);
  HB_INTERNAL void fini ();

#define HB_OT_TABLE_ORDER(Namespace, Type) \
    HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
  enum order_t
  {
    ORDER_ZERO,
#define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
#include "hb-ot-face-table-list.hh"
#undef HB_OT_TABLE
  };

  hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_TABLE(Namespace, Type) \
  hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#define HB_OT_ACCELERATOR(Namespace, Type) \
  hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
#undef HB_OT_TABLE
};

#endif /* HB_OT_FACE_HH */


text:
/*
 * Copyright © 2007,2008,2009  Red Hat, Inc.
 * Copyright © 2012,2013  Google, Inc.
 * Copyright © 2019, Facebook Inc.
 *
 *  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.
 *
 * Red Hat Author(s): Behdad Esfahbod
 * Google Author(s): Behdad Esfahbod
 * Facebook Author(s): Behdad Esfahbod
 */

#ifndef HB_OT_FACE_TABLE_LIST_HH
#define HB_OT_FACE_TABLE_LIST_HH
#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */

#ifndef HB_OT_ACCELERATOR
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_ACCELERATOR_UNDEF
#endif

/* This lists font tables that the hb_face_t will contain and lazily
 * load.  Don't add a table unless it's used though.  This is not
 * exactly free. */

/* v--- Add new tables in the right place here. */

/* OpenType fundamentals. */
HB_OT_TABLE (OT, head)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
HB_OT_TABLE (OT, hhea)
HB_OT_ACCELERATOR (OT, hmtx)
HB_OT_TABLE (OT, OS2)
#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS)
HB_OT_ACCELERATOR (OT, post)
#endif
#ifndef HB_NO_NAME
HB_OT_ACCELERATOR (OT, name)
#endif
#ifndef HB_NO_STAT
HB_OT_TABLE (OT, STAT)
#endif
#ifndef HB_NO_META
HB_OT_ACCELERATOR (OT, meta)
#endif

/* Vertical layout. */
HB_OT_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)

/* TrueType outlines. */
HB_OT_ACCELERATOR (OT, glyf)

/* CFF outlines. */
#ifndef HB_NO_CFF
HB_OT_ACCELERATOR (OT, cff1)
HB_OT_ACCELERATOR (OT, cff2)
HB_OT_TABLE (OT, VORG)
#endif

/* OpenType variations. */
#ifndef HB_NO_VAR
HB_OT_TABLE (OT, fvar)
HB_OT_TABLE (OT, avar)
HB_OT_ACCELERATOR (OT, gvar)
HB_OT_TABLE (OT, MVAR)
#endif

/* Legacy kern. */
#ifndef HB_NO_OT_KERN
HB_OT_TABLE (OT, kern)
#endif

/* OpenType shaping. */
#ifndef HB_NO_OT_LAYOUT
HB_OT_ACCELERATOR (OT, GDEF)
HB_OT_ACCELERATOR (OT, GSUB)
HB_OT_ACCELERATOR (OT, GPOS)
//HB_OT_TABLE (OT, JSTF)
#endif

/* OpenType baseline. */
#ifndef HB_NO_BASE
HB_OT_TABLE (OT, BASE)
#endif

/* AAT shaping. */
#ifndef HB_NO_AAT
HB_OT_TABLE (AAT, morx)
HB_OT_TABLE (AAT, mort)
HB_OT_TABLE (AAT, kerx)
HB_OT_TABLE (AAT, ankr)
HB_OT_TABLE (AAT, trak)
HB_OT_TABLE (AAT, lcar)
HB_OT_TABLE (AAT, ltag)
HB_OT_TABLE (AAT, feat)
// HB_OT_TABLE (AAT, opbd)
#endif

/* OpenType color fonts. */
#ifndef HB_NO_COLOR
HB_OT_TABLE (OT, COLR)
HB_OT_TABLE (OT, CPAL)
HB_OT_ACCELERATOR (OT, CBDT)
HB_OT_ACCELERATOR (OT, sbix)
HB_OT_ACCELERATOR (OT, SVG)
#endif

/* OpenType math. */
#ifndef HB_NO_MATH
HB_OT_TABLE (OT, MATH)
#endif

#ifdef _HB_OT_ACCELERATOR_UNDEF
#undef HB_OT_ACCELERATOR
#endif


text:
/*
 * Copyright © 2018  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Rod Sheeter
 */

#ifndef HB_SUBSET_H
#define HB_SUBSET_H

#include "hb.h"

HB_BEGIN_DECLS

/*
 * hb_subset_input_t
 *
 * Things that change based on the input. Characters to keep, etc.
 */

typedef struct hb_subset_input_t hb_subset_input_t;

HB_EXTERN hb_subset_input_t *
hb_subset_input_create_or_fail (void);

HB_EXTERN hb_subset_input_t *
hb_subset_input_reference (hb_subset_input_t *subset_input);

HB_EXTERN void
hb_subset_input_destroy (hb_subset_input_t *subset_input);

HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *subset_input);

HB_EXTERN hb_set_t *
hb_subset_input_glyph_set (hb_subset_input_t *subset_input);

HB_EXTERN hb_set_t *
hb_subset_input_nameid_set (hb_subset_input_t *subset_input);

HB_EXTERN hb_set_t *
hb_subset_input_namelangid_set (hb_subset_input_t *subset_input);

HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input);

HB_EXTERN void
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
				hb_bool_t drop_hints);
HB_EXTERN hb_bool_t
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);

HB_EXTERN void
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
				    hb_bool_t desubroutinize);
HB_EXTERN hb_bool_t
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);

HB_EXTERN void
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
				 hb_bool_t retain_gids);
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);

HB_EXTERN void
hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
				 hb_bool_t name_legacy);
HB_EXTERN hb_bool_t
hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input);

/* hb_subset () */
HB_EXTERN hb_face_t *
hb_subset (hb_face_t *source, hb_subset_input_t *input);

HB_END_DECLS

#endif /* HB_SUBSET_H */


text:
/*
 * Copyright © 2012  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_H_IN
#error "Include <hb.h> instead."
#endif

#ifndef HB_SET_H
#define HB_SET_H

#include "hb-common.h"

HB_BEGIN_DECLS

/*
 * Since: 0.9.21
 */
#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1)

typedef struct hb_set_t hb_set_t;

HB_EXTERN hb_set_t *
hb_set_create (void);

HB_EXTERN hb_set_t *
hb_set_get_empty (void);

HB_EXTERN hb_set_t *
hb_set_reference (hb_set_t *set);

HB_EXTERN void
hb_set_destroy (hb_set_t *set);

HB_EXTERN hb_bool_t
hb_set_set_user_data (hb_set_t           *set,
		      hb_user_data_key_t *key,
		      void *              data,
		      hb_destroy_func_t   destroy,
		      hb_bool_t           replace);

HB_EXTERN void *
hb_set_get_user_data (hb_set_t           *set,
		      hb_user_data_key_t *key);

/* Returns false if allocation has failed before */
HB_EXTERN hb_bool_t
hb_set_allocation_successful (const hb_set_t *set);

HB_EXTERN void
hb_set_clear (hb_set_t *set);

HB_EXTERN hb_bool_t
hb_set_is_empty (const hb_set_t *set);

HB_EXTERN hb_bool_t
hb_set_has (const hb_set_t *set,
	    hb_codepoint_t  codepoint);

HB_EXTERN void
hb_set_add (hb_set_t       *set,
	    hb_codepoint_t  codepoint);

HB_EXTERN void
hb_set_add_range (hb_set_t       *set,
		  hb_codepoint_t  first,
		  hb_codepoint_t  last);

HB_EXTERN void
hb_set_del (hb_set_t       *set,
	    hb_codepoint_t  codepoint);

HB_EXTERN void
hb_set_del_range (hb_set_t       *set,
		  hb_codepoint_t  first,
		  hb_codepoint_t  last);

HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
		 const hb_set_t *other);

HB_EXTERN hb_bool_t
hb_set_is_subset (const hb_set_t *set,
		  const hb_set_t *larger_set);

HB_EXTERN void
hb_set_set (hb_set_t       *set,
	    const hb_set_t *other);

HB_EXTERN void
hb_set_union (hb_set_t       *set,
	      const hb_set_t *other);

HB_EXTERN void
hb_set_intersect (hb_set_t       *set,
		  const hb_set_t *other);

HB_EXTERN void
hb_set_subtract (hb_set_t       *set,
		 const hb_set_t *other);

HB_EXTERN void
hb_set_symmetric_difference (hb_set_t       *set,
			     const hb_set_t *other);

HB_EXTERN unsigned int
hb_set_get_population (const hb_set_t *set);

/* Returns HB_SET_VALUE_INVALID if set empty. */
HB_EXTERN hb_codepoint_t
hb_set_get_min (const hb_set_t *set);

/* Returns HB_SET_VALUE_INVALID if set empty. */
HB_EXTERN hb_codepoint_t
hb_set_get_max (const hb_set_t *set);

/* Pass HB_SET_VALUE_INVALID in to get started. */
HB_EXTERN hb_bool_t
hb_set_next (const hb_set_t *set,
	     hb_codepoint_t *codepoint);

/* Pass HB_SET_VALUE_INVALID in to get started. */
HB_EXTERN hb_bool_t
hb_set_previous (const hb_set_t *set,
		 hb_codepoint_t *codepoint);

/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
HB_EXTERN hb_bool_t
hb_set_next_range (const hb_set_t *set,
		   hb_codepoint_t *first,
		   hb_codepoint_t *last);

/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
HB_EXTERN hb_bool_t
hb_set_previous_range (const hb_set_t *set,
		       hb_codepoint_t *first,
		       hb_codepoint_t *last);

HB_END_DECLS

#endif /* HB_SET_H */


text:
#!/bin/sh

LC_ALL=C
export LC_ALL

test -z "$srcdir" && srcdir=.
stat=0

test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'`

echo 'Checking that public header files #include "hb-common.h" or "hb.h" first (or none)'

for x in $HBHEADERS; do
	test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
	grep '#.*\<include\>' "$x" /dev/null | head -n 1
done |
grep -v '"hb-common[.]h"' |
grep -v '"hb[.]h"' |
grep -v 'hb-common[.]h:' |
grep -v 'hb[.]h:' |
grep . >&2 && stat=1

echo 'Checking that source files #include a private header first (or none)'

for x in $HBSOURCES; do
	test -f "$srcdir/$x" -a ! -f "$x" && x="$srcdir/$x"
	grep '#.*\<include\>' "$x" /dev/null | head -n 1
done |
grep -v '"hb-.*[.]hh"' |
grep -v 'hb[.]hh' |
grep . >&2 && stat=1

echo 'Checking that there is no #include <hb-*.h>'
for x in $HBHEADERS $HBSOURCES; do
	test -f "$srcdir/$x" && x="$srcdir/$x"
	grep '#.*\<include\>.*<.*hb' "$x" /dev/null >&2 && stat=1
done

exit $stat


text:
/*
 * Copyright © 2018  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_AAT_MAP_HH
#define HB_AAT_MAP_HH

#include "hb.hh"

struct hb_aat_map_t
{
  friend struct hb_aat_map_builder_t;

  public:

  void init ()
  {
    memset (this, 0, sizeof (*this));
    chain_flags.init ();
  }
  void fini () { chain_flags.fini (); }

  public:
  hb_vector_t<hb_mask_t> chain_flags;
};

struct hb_aat_map_builder_t
{
  public:

  HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
				    const hb_segment_properties_t *props_ HB_UNUSED) :
				      face (face_) {}

  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);

  HB_INTERNAL void compile (hb_aat_map_t  &m);

  public:
  struct feature_info_t
  {
    hb_aat_layout_feature_type_t  type;
    hb_aat_layout_feature_selector_t  setting;
    bool is_exclusive;
    unsigned  seq; /* For stable sorting only. */

    HB_INTERNAL static int cmp (const void *pa, const void *pb)
    {
      const feature_info_t *a = (const feature_info_t *) pa;
      const feature_info_t *b = (const feature_info_t *) pb;
      if (a->type != b->type) return (a->type < b->type ? -1 : 1);
      if (!a->is_exclusive &&
	  (a->setting & ~1) != (b->setting & ~1)) return (a->setting < b->setting ? -1 : 1);
	    return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
    }

    /* compares type & setting only, not is_exclusive flag or seq number */
    int cmp (const feature_info_t& f) const
    {
      return (f.type != type) ? (f.type < type ? -1 : 1) :
	     (f.setting != setting) ? (f.setting < setting ? -1 : 1) : 0;
    }
  };

  public:
  hb_face_t *face;

  public:
  hb_sorted_vector_t<feature_info_t> features;
};

#endif /* HB_AAT_MAP_HH */


text:
/*
 * Copyright © 2012  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_SHAPER_IMPL_HH
#define HB_SHAPER_IMPL_HH

#include "hb.hh"

#include "hb-shaper.hh"
#include "hb-face.hh"
#include "hb-font.hh"
#include "hb-shape-plan.hh"
#include "hb-buffer.hh"

#endif /* HB_SHAPER_IMPL_HH */


text:
/*
 * Copyright © 2019-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.
 */

#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
 *
 * Sets move-to callback to the draw functions object.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t        *funcs,
				hb_draw_move_to_func_t  move_to)
{
  if (unlikely (hb_object_is_immutable (funcs))) return;
  funcs->move_to = move_to;
}

/**
 * hb_draw_funcs_set_line_to_func:
 * @funcs: draw functions object
 * @line_to: line-to callback
 *
 * Sets line-to callback to the draw functions object.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t        *funcs,
				hb_draw_line_to_func_t  line_to)
{
  if (unlikely (hb_object_is_immutable (funcs))) return;
  funcs->line_to = line_to;
}

/**
 * hb_draw_funcs_set_quadratic_to_func:
 * @funcs: draw functions object
 * @move_to: quadratic-to callback
 *
 * Sets quadratic-to callback to the draw functions object.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t             *funcs,
				     hb_draw_quadratic_to_func_t  quadratic_to)
{
  if (unlikely (hb_object_is_immutable (funcs))) return;
  funcs->quadratic_to = quadratic_to;
  funcs->is_quadratic_to_set = true;
}

/**
 * hb_draw_funcs_set_cubic_to_func:
 * @funcs: draw functions
 * @cubic_to: cubic-to callback
 *
 * Sets cubic-to callback to the draw functions object.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t         *funcs,
				 hb_draw_cubic_to_func_t  cubic_to)
{
  if (unlikely (hb_object_is_immutable (funcs))) return;
  funcs->cubic_to = cubic_to;
}

/**
 * hb_draw_funcs_set_close_path_func:
 * @funcs: draw functions object
 * @close_path: close-path callback
 *
 * Sets close-path callback to the draw functions object.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t           *funcs,
				   hb_draw_close_path_func_t  close_path)
{
  if (unlikely (hb_object_is_immutable (funcs))) return;
  funcs->close_path = close_path;
}

static void
_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}

static void
_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}

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) {}

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) {}

static void
_close_path_nil (void *user_data HB_UNUSED) {}

/**
 * hb_draw_funcs_create:
 *
 * Creates a new draw callbacks object.
 *
 * Since: EXPERIMENTAL
 **/
hb_draw_funcs_t *
hb_draw_funcs_create ()
{
  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));

  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_draw_funcs_reference:
 * @funcs: draw functions
 *
 * Add to callbacks object refcount.
 *
 * Returns: The same object.
 * Since: EXPERIMENTAL
 **/
hb_draw_funcs_t *
hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
{
  return hb_object_reference (funcs);
}

/**
 * hb_draw_funcs_destroy:
 * @funcs: draw functions
 *
 * Decreases refcount of callbacks object and deletes the object if it reaches
 * to zero.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
{
  if (!hb_object_destroy (funcs)) return;

  free (funcs);
}

/**
 * hb_draw_funcs_make_immutable:
 * @funcs: draw functions
 *
 * Makes funcs object immutable.
 *
 * Since: EXPERIMENTAL
 **/
void
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
{
  if (hb_object_is_immutable (funcs))
    return;

  hb_object_make_immutable (funcs);
}

/**
 * hb_draw_funcs_is_immutable:
 * @funcs: draw functions
 *
 * Checks whether funcs is immutable.
 *
 * Returns: If is immutable.
 * Since: EXPERIMENTAL
 **/
hb_bool_t
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
{
  return hb_object_is_immutable (funcs);
}

/**
 * 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
 *
 * Draw a glyph.
 *
 * Returns: Whether the font had the glyph and the operation completed successfully.
 * Since: EXPERIMENTAL
 **/
hb_bool_t
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
		    const hb_draw_funcs_t *funcs,
		    void *user_data)
{
  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

  return false;
}

#endif
#endif


text:
/*
 * Copyright © 2019  Adobe, Inc.
 *
 *  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.
 *
 * Adobe Author(s): Michiharu Ariza
 */

#ifndef HB_OT_CFF1_STD_STR_HH
#if 0 /* Make checks happy. */
#define HB_OT_CFF1_STD_STR_HH
#include "hb.hh"
#endif

_S(".notdef")
_S("space")
_S("exclam")
_S("quotedbl")
_S("numbersign")
_S("dollar")
_S("percent")
_S("ampersand")
_S("quoteright")
_S("parenleft")
_S("parenright")
_S("asterisk")
_S("plus")
_S("comma")
_S("hyphen")
_S("period")
_S("slash")
_S("zero")
_S("one")
_S("two")
_S("three")
_S("four")
_S("five")
_S("six")
_S("seven")
_S("eight")
_S("nine")
_S("colon")
_S("semicolon")
_S("less")
_S("equal")
_S("greater")
_S("question")
_S("at")
_S("A")
_S("B")
_S("C")
_S("D")
_S("E")
_S("F")
_S("G")
_S("H")
_S("I")
_S("J")
_S("K")
_S("L")
_S("M")
_S("N")
_S("O")
_S("P")
_S("Q")
_S("R")
_S("S")
_S("T")
_S("U")
_S("V")
_S("W")
_S("X")
_S("Y")
_S("Z")
_S("bracketleft")
_S("backslash")
_S("bracketright")
_S("asciicircum")
_S("underscore")
_S("quoteleft")
_S("a")
_S("b")
_S("c")
_S("d")
_S("e")
_S("f")
_S("g")
_S("h")
_S("i")
_S("j")
_S("k")
_S("l")
_S("m")
_S("n")
_S("o")
_S("p")
_S("q")
_S("r")
_S("s")
_S("t")
_S("u")
_S("v")
_S("w")
_S("x")
_S("y")
_S("z")
_S("braceleft")
_S("bar")
_S("braceright")
_S("asciitilde")
_S("exclamdown")
_S("cent")
_S("sterling")
_S("fraction")
_S("yen")
_S("florin")
_S("section")
_S("currency")
_S("quotesingle")
_S("quotedblleft")
_S("guillemotleft")
_S("guilsinglleft")
_S("guilsinglright")
_S("fi")
_S("fl")
_S("endash")
_S("dagger")
_S("daggerdbl")
_S("periodcentered")
_S("paragraph")
_S("bullet")
_S("quotesinglbase")
_S("quotedblbase")
_S("quotedblright")
_S("guillemotright")
_S("ellipsis")
_S("perthousand")
_S("questiondown")
_S("grave")
_S("acute")
_S("circumflex")
_S("tilde")
_S("macron")
_S("breve")
_S("dotaccent")
_S("dieresis")
_S("ring")
_S("cedilla")
_S("hungarumlaut")
_S("ogonek")
_S("caron")
_S("emdash")
_S("AE")
_S("ordfeminine")
_S("Lslash")
_S("Oslash")
_S("OE")
_S("ordmasculine")
_S("ae")
_S("dotlessi")
_S("lslash")
_S("oslash")
_S("oe")
_S("germandbls")
_S("onesuperior")
_S("logicalnot")
_S("mu")
_S("trademark")
_S("Eth")
_S("onehalf")
_S("plusminus")
_S("Thorn")
_S("onequarter")
_S("divide")
_S("brokenbar")
_S("degree")
_S("thorn")
_S("threequarters")
_S("twosuperior")
_S("registered")
_S("minus")
_S("eth")
_S("multiply")
_S("threesuperior")
_S("copyright")
_S("Aacute")
_S("Acircumflex")
_S("Adieresis")
_S("Agrave")
_S("Aring")
_S("Atilde")
_S("Ccedilla")
_S("Eacute")
_S("Ecircumflex")
_S("Edieresis")
_S("Egrave")
_S("Iacute")
_S("Icircumflex")
_S("Idieresis")
_S("Igrave")
_S("Ntilde")
_S("Oacute")
_S("Ocircumflex")
_S("Odieresis")
_S("Ograve")
_S("Otilde")
_S("Scaron")
_S("Uacute")
_S("Ucircumflex")
_S("Udieresis")
_S("Ugrave")
_S("Yacute")
_S("Ydieresis")
_S("Zcaron")
_S("aacute")
_S("acircumflex")
_S("adieresis")
_S("agrave")
_S("aring")
_S("atilde")
_S("ccedilla")
_S("eacute")
_S("ecircumflex")
_S("edieresis")
_S("egrave")
_S("iacute")
_S("icircumflex")
_S("idieresis")
_S("igrave")
_S("ntilde")
_S("oacute")
_S("ocircumflex")
_S("odieresis")
_S("ograve")
_S("otilde")
_S("scaron")
_S("uacute")
_S("ucircumflex")
_S("udieresis")
_S("ugrave")
_S("yacute")
_S("ydieresis")
_S("zcaron")
_S("exclamsmall")
_S("Hungarumlautsmall")
_S("dollaroldstyle")
_S("dollarsuperior")
_S("ampersandsmall")
_S("Acutesmall")
_S("parenleftsuperior")
_S("parenrightsuperior")
_S("twodotenleader")
_S("onedotenleader")
_S("zerooldstyle")
_S("oneoldstyle")
_S("twooldstyle")
_S("threeoldstyle")
_S("fouroldstyle")
_S("fiveoldstyle")
_S("sixoldstyle")
_S("sevenoldstyle")
_S("eightoldstyle")
_S("nineoldstyle")
_S("commasuperior")
_S("threequartersemdash")
_S("periodsuperior")
_S("questionsmall")
_S("asuperior")
_S("bsuperior")
_S("centsuperior")
_S("dsuperior")
_S("esuperior")
_S("isuperior")
_S("lsuperior")
_S("msuperior")
_S("nsuperior")
_S("osuperior")
_S("rsuperior")
_S("ssuperior")
_S("tsuperior")
_S("ff")
_S("ffi")
_S("ffl")
_S("parenleftinferior")
_S("parenrightinferior")
_S("Circumflexsmall")
_S("hyphensuperior")
_S("Gravesmall")
_S("Asmall")
_S("Bsmall")
_S("Csmall")
_S("Dsmall")
_S("Esmall")
_S("Fsmall")
_S("Gsmall")
_S("Hsmall")
_S("Ismall")
_S("Jsmall")
_S("Ksmall")
_S("Lsmall")
_S("Msmall")
_S("Nsmall")
_S("Osmall")
_S("Psmall")
_S("Qsmall")
_S("Rsmall")
_S("Ssmall")
_S("Tsmall")
_S("Usmall")
_S("Vsmall")
_S("Wsmall")
_S("Xsmall")
_S("Ysmall")
_S("Zsmall")
_S("colonmonetary")
_S("onefitted")
_S("rupiah")
_S("Tildesmall")
_S("exclamdownsmall")
_S("centoldstyle")
_S("Lslashsmall")
_S("Scaronsmall")
_S("Zcaronsmall")
_S("Dieresissmall")
_S("Brevesmall")
_S("Caronsmall")
_S("Dotaccentsmall")
_S("Macronsmall")
_S("figuredash")
_S("hypheninferior")
_S("Ogoneksmall")
_S("Ringsmall")
_S("Cedillasmall")
_S("questiondownsmall")
_S("oneeighth")
_S("threeeighths")
_S("fiveeighths")
_S("seveneighths")
_S("onethird")
_S("twothirds")
_S("zerosuperior")
_S("foursuperior")
_S("fivesuperior")
_S("sixsuperior")
_S("sevensuperior")
_S("eightsuperior")
_S("ninesuperior")
_S("zeroinferior")
_S("oneinferior")
_S("twoinferior")
_S("threeinferior")
_S("fourinferior")
_S("fiveinferior")
_S("sixinferior")
_S("seveninferior")
_S("eightinferior")
_S("nineinferior")
_S("centinferior")
_S("dollarinferior")
_S("periodinferior")
_S("commainferior")
_S("Agravesmall")
_S("Aacutesmall")
_S("Acircumflexsmall")
_S("Atildesmall")
_S("Adieresissmall")
_S("Aringsmall")
_S("AEsmall")
_S("Ccedillasmall")
_S("Egravesmall")
_S("Eacutesmall")
_S("Ecircumflexsmall")
_S("Edieresissmall")
_S("Igravesmall")
_S("Iacutesmall")
_S("Icircumflexsmall")
_S("Idieresissmall")
_S("Ethsmall")
_S("Ntildesmall")
_S("Ogravesmall")
_S("Oacutesmall")
_S("Ocircumflexsmall")
_S("Otildesmall")
_S("Odieresissmall")
_S("OEsmall")
_S("Oslashsmall")
_S("Ugravesmall")
_S("Uacutesmall")
_S("Ucircumflexsmall")
_S("Udieresissmall")
_S("Yacutesmall")
_S("Thornsmall")
_S("Ydieresissmall")
_S("001.000")
_S("001.001")
_S("001.002")
_S("001.003")
_S("Black")
_S("Bold")
_S("Book")
_S("Light")
_S("Medium")
_S("Regular")
_S("Roman")
_S("Semibold")

#endif /* HB_OT_CFF1_STD_STR_HH */


text:
/*
 * Copyright © 2010,2011,2013  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#include "hb.hh"

#include "hb.h"
#include "hb-ot.h"
#ifdef HAVE_FREETYPE
#include "hb-ft.h"
#endif

#include <stdio.h>

#ifdef HB_NO_OPEN
#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
#endif

int
main (int argc, char **argv)
{
  bool ret = true;

#ifndef HB_NO_BUFFER_SERIALIZE

  if (argc != 2) {
    fprintf (stderr, "usage: %s font-file\n", argv[0]);
    exit (1);
  }

  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
  hb_face_t *face = hb_face_create (blob, 0 /* first face */);
  hb_blob_destroy (blob);
  blob = nullptr;

  unsigned int upem = hb_face_get_upem (face);
  hb_font_t *font = hb_font_create (face);
  hb_face_destroy (face);
  hb_font_set_scale (font, upem, upem);
  hb_ot_font_set_funcs (font);
#ifdef HAVE_FREETYPE
  //hb_ft_font_set_funcs (font);
#endif

  hb_buffer_t *buf;
  buf = hb_buffer_create ();

  char line[BUFSIZ], out[BUFSIZ];
  while (fgets (line, sizeof(line), stdin))
  {
    hb_buffer_clear_contents (buf);

    const char *p = line;
    while (hb_buffer_deserialize_glyphs (buf,
					 p, -1, &p,
					 font,
					 HB_BUFFER_SERIALIZE_FORMAT_JSON))
      ;
    if (*p && *p != '\n')
      ret = false;

    hb_buffer_serialize_glyphs (buf, 0, hb_buffer_get_length (buf),
				out, sizeof (out), nullptr,
				font, HB_BUFFER_SERIALIZE_FORMAT_JSON,
				HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
    puts (out);
  }

  hb_buffer_destroy (buf);

  hb_font_destroy (font);

#endif

  return !ret;
}