text:
/*
 * Copyright © 2009  Red Hat, Inc.
 * Copyright © 2011  Codethink Limited
 * 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.
 *
 * Red Hat Author(s): Behdad Esfahbod
 * Codethink Author(s): Ryan Lortie
 * Google Author(s): Behdad Esfahbod
 */

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

#ifndef HB_UNICODE_H
#define HB_UNICODE_H

#include "hb-common.h"

HB_BEGIN_DECLS

/**
 * HB_UNICODE_MAX
 *
 * Since: 1.9.0
 **/
#define HB_UNICODE_MAX 0x10FFFFu

/* hb_unicode_general_category_t */

/* Unicode Character Database property: General_Category (gc) */
typedef enum
{
  HB_UNICODE_GENERAL_CATEGORY_CONTROL,			/* Cc */
  HB_UNICODE_GENERAL_CATEGORY_FORMAT,			/* Cf */
  HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED,		/* Cn */
  HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE,		/* Co */
  HB_UNICODE_GENERAL_CATEGORY_SURROGATE,		/* Cs */
  HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER,		/* Ll */
  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER,		/* Lm */
  HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER,		/* Lo */
  HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER,		/* Lt */
  HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER,		/* Lu */
  HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK,		/* Mc */
  HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK,		/* Me */
  HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK,		/* Mn */
  HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER,		/* Nd */
  HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER,		/* Nl */
  HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER,		/* No */
  HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION,	/* Pc */
  HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION,		/* Pd */
  HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION,	/* Pe */
  HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION,	/* Pf */
  HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION,	/* Pi */
  HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION,	/* Po */
  HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION,		/* Ps */
  HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL,		/* Sc */
  HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL,		/* Sk */
  HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL,		/* Sm */
  HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL,		/* So */
  HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR,		/* Zl */
  HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR,	/* Zp */
  HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR		/* Zs */
} hb_unicode_general_category_t;

/* hb_unicode_combining_class_t */

/* Note: newer versions of Unicode may add new values.  Clients should be ready to handle
 * any value in the 0..254 range being returned from hb_unicode_combining_class().
 */

/* Unicode Character Database property: Canonical_Combining_Class (ccc) */
typedef enum
{
  HB_UNICODE_COMBINING_CLASS_NOT_REORDERED	= 0,
  HB_UNICODE_COMBINING_CLASS_OVERLAY		= 1,
  HB_UNICODE_COMBINING_CLASS_NUKTA		= 7,
  HB_UNICODE_COMBINING_CLASS_KANA_VOICING	= 8,
  HB_UNICODE_COMBINING_CLASS_VIRAMA		= 9,

  /* Hebrew */
  HB_UNICODE_COMBINING_CLASS_CCC10	=  10,
  HB_UNICODE_COMBINING_CLASS_CCC11	=  11,
  HB_UNICODE_COMBINING_CLASS_CCC12	=  12,
  HB_UNICODE_COMBINING_CLASS_CCC13	=  13,
  HB_UNICODE_COMBINING_CLASS_CCC14	=  14,
  HB_UNICODE_COMBINING_CLASS_CCC15	=  15,
  HB_UNICODE_COMBINING_CLASS_CCC16	=  16,
  HB_UNICODE_COMBINING_CLASS_CCC17	=  17,
  HB_UNICODE_COMBINING_CLASS_CCC18	=  18,
  HB_UNICODE_COMBINING_CLASS_CCC19	=  19,
  HB_UNICODE_COMBINING_CLASS_CCC20	=  20,
  HB_UNICODE_COMBINING_CLASS_CCC21	=  21,
  HB_UNICODE_COMBINING_CLASS_CCC22	=  22,
  HB_UNICODE_COMBINING_CLASS_CCC23	=  23,
  HB_UNICODE_COMBINING_CLASS_CCC24	=  24,
  HB_UNICODE_COMBINING_CLASS_CCC25	=  25,
  HB_UNICODE_COMBINING_CLASS_CCC26	=  26,

  /* Arabic */
  HB_UNICODE_COMBINING_CLASS_CCC27	=  27,
  HB_UNICODE_COMBINING_CLASS_CCC28	=  28,
  HB_UNICODE_COMBINING_CLASS_CCC29	=  29,
  HB_UNICODE_COMBINING_CLASS_CCC30	=  30,
  HB_UNICODE_COMBINING_CLASS_CCC31	=  31,
  HB_UNICODE_COMBINING_CLASS_CCC32	=  32,
  HB_UNICODE_COMBINING_CLASS_CCC33	=  33,
  HB_UNICODE_COMBINING_CLASS_CCC34	=  34,
  HB_UNICODE_COMBINING_CLASS_CCC35	=  35,

  /* Syriac */
  HB_UNICODE_COMBINING_CLASS_CCC36	=  36,

  /* Telugu */
  HB_UNICODE_COMBINING_CLASS_CCC84	=  84,
  HB_UNICODE_COMBINING_CLASS_CCC91	=  91,

  /* Thai */
  HB_UNICODE_COMBINING_CLASS_CCC103	= 103,
  HB_UNICODE_COMBINING_CLASS_CCC107	= 107,

  /* Lao */
  HB_UNICODE_COMBINING_CLASS_CCC118	= 118,
  HB_UNICODE_COMBINING_CLASS_CCC122	= 122,

  /* Tibetan */
  HB_UNICODE_COMBINING_CLASS_CCC129	= 129,
  HB_UNICODE_COMBINING_CLASS_CCC130	= 130,
  HB_UNICODE_COMBINING_CLASS_CCC133	= 132,

  HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT	= 200,
  HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW		= 202,
  HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE		= 214,
  HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT	= 216,
  HB_UNICODE_COMBINING_CLASS_BELOW_LEFT			= 218,
  HB_UNICODE_COMBINING_CLASS_BELOW			= 220,
  HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT		= 222,
  HB_UNICODE_COMBINING_CLASS_LEFT			= 224,
  HB_UNICODE_COMBINING_CLASS_RIGHT			= 226,
  HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT			= 228,
  HB_UNICODE_COMBINING_CLASS_ABOVE			= 230,
  HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT		= 232,
  HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW		= 233,
  HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE		= 234,

  HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT		= 240,

  HB_UNICODE_COMBINING_CLASS_INVALID	= 255
} hb_unicode_combining_class_t;

/*
 * hb_unicode_funcs_t
 */

typedef struct hb_unicode_funcs_t hb_unicode_funcs_t;

/*
 * just give me the best implementation you've got there.
 */
HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_default (void);

HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_create (hb_unicode_funcs_t *parent);

HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_empty (void);

HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);

HB_EXTERN void
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);

HB_EXTERN hb_bool_t
hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
				hb_user_data_key_t *key,
				void *              data,
				hb_destroy_func_t   destroy,
				hb_bool_t           replace);

HB_EXTERN void *
hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
				hb_user_data_key_t *key);

HB_EXTERN void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);

HB_EXTERN hb_bool_t
hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);

HB_EXTERN hb_unicode_funcs_t *
hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);

/*
 * funcs
 */

/* typedefs */

typedef hb_unicode_combining_class_t	(*hb_unicode_combining_class_func_t)	(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      unicode,
										 void               *user_data);
typedef hb_unicode_general_category_t	(*hb_unicode_general_category_func_t)	(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      unicode,
										 void               *user_data);
typedef hb_codepoint_t			(*hb_unicode_mirroring_func_t)		(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      unicode,
										 void               *user_data);
typedef hb_script_t			(*hb_unicode_script_func_t)		(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      unicode,
										 void               *user_data);

typedef hb_bool_t			(*hb_unicode_compose_func_t)		(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      a,
										 hb_codepoint_t      b,
										 hb_codepoint_t     *ab,
										 void               *user_data);
typedef hb_bool_t			(*hb_unicode_decompose_func_t)		(hb_unicode_funcs_t *ufuncs,
										 hb_codepoint_t      ab,
										 hb_codepoint_t     *a,
										 hb_codepoint_t     *b,
										 void               *user_data);

/* setters */

/**
 * hb_unicode_funcs_set_combining_class_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
					   hb_unicode_combining_class_func_t func,
					   void *user_data, hb_destroy_func_t destroy);

/**
 * hb_unicode_funcs_set_general_category_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
					    hb_unicode_general_category_func_t func,
					    void *user_data, hb_destroy_func_t destroy);

/**
 * hb_unicode_funcs_set_mirroring_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
				     hb_unicode_mirroring_func_t func,
				     void *user_data, hb_destroy_func_t destroy);

/**
 * hb_unicode_funcs_set_script_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
				  hb_unicode_script_func_t func,
				  void *user_data, hb_destroy_func_t destroy);

/**
 * hb_unicode_funcs_set_compose_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
				   hb_unicode_compose_func_t func,
				   void *user_data, hb_destroy_func_t destroy);

/**
 * hb_unicode_funcs_set_decompose_func:
 * @ufuncs: a Unicode function structure
 * @func: (closure user_data) (destroy destroy) (scope notified):
 * @user_data:
 * @destroy:
 *
 *
 *
 * Since: 0.9.2
 **/
HB_EXTERN void
hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
				     hb_unicode_decompose_func_t func,
				     void *user_data, hb_destroy_func_t destroy);

/* accessors */

/**
 * hb_unicode_combining_class:
 *
 * Since: 0.9.2
 **/
HB_EXTERN hb_unicode_combining_class_t
hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
			    hb_codepoint_t unicode);

/**
 * hb_unicode_general_category:
 *
 * Since: 0.9.2
 **/
HB_EXTERN hb_unicode_general_category_t
hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
			     hb_codepoint_t unicode);

/**
 * hb_unicode_mirroring:
 *
 * Since: 0.9.2
 **/
HB_EXTERN hb_codepoint_t
hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
		      hb_codepoint_t unicode);

/**
 * hb_unicode_script:
 *
 * Since: 0.9.2
 **/
HB_EXTERN hb_script_t
hb_unicode_script (hb_unicode_funcs_t *ufuncs,
		   hb_codepoint_t unicode);

HB_EXTERN hb_bool_t
hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
		    hb_codepoint_t      a,
		    hb_codepoint_t      b,
		    hb_codepoint_t     *ab);

HB_EXTERN hb_bool_t
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
		      hb_codepoint_t      ab,
		      hb_codepoint_t     *a,
		      hb_codepoint_t     *b);

HB_END_DECLS

#endif /* HB_UNICODE_H */


text:
/*
 * Copyright © 2007  Chris Wilson
 * Copyright © 2009,2010  Red Hat, Inc.
 * 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.
 *
 * Contributor(s):
 *	Chris Wilson <chris@chris-wilson.co.uk>
 * Red Hat Author(s): Behdad Esfahbod
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_MUTEX_HH
#define HB_MUTEX_HH

#include "hb.hh"

/* mutex */

/* We need external help for these */

#if defined(HB_MUTEX_IMPL_INIT) \
 && defined(hb_mutex_impl_init) \
 && defined(hb_mutex_impl_lock) \
 && defined(hb_mutex_impl_unlock) \
 && defined(hb_mutex_impl_finish)

/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */

#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))

#include <pthread.h>
typedef pthread_mutex_t hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)

#elif !defined(HB_NO_MT) && defined(_WIN32)

#include <windows.h>
typedef CRITICAL_SECTION hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT	{0}
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
#define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
#else
#define hb_mutex_impl_init(M)	InitializeCriticalSection (M)
#endif
#define hb_mutex_impl_lock(M)	EnterCriticalSection (M)
#define hb_mutex_impl_unlock(M)	LeaveCriticalSection (M)
#define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)

#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)

#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
# include <sched.h>
# define HB_SCHED_YIELD() sched_yield ()
#else
# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
#endif

/* This actually is not a totally awful implementation. */
typedef volatile int hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT	0
#define hb_mutex_impl_init(M)	*(M) = 0
#define hb_mutex_impl_lock(M)	HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
#define hb_mutex_impl_unlock(M)	__sync_lock_release (M)
#define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END

#elif defined(HB_NO_MT)

typedef int hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT	0
#define hb_mutex_impl_init(M)	HB_STMT_START {} HB_STMT_END
#define hb_mutex_impl_lock(M)	HB_STMT_START {} HB_STMT_END
#define hb_mutex_impl_unlock(M)	HB_STMT_START {} HB_STMT_END
#define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END

#else

#error "Could not find any system to define mutex macros."
#error "Check hb-mutex.hh for possible resolutions."

#endif

#define HB_MUTEX_INIT		{HB_MUTEX_IMPL_INIT}

struct hb_mutex_t
{
  hb_mutex_impl_t m;

  void init   () { hb_mutex_impl_init   (&m); }
  void lock   () { hb_mutex_impl_lock   (&m); }
  void unlock () { hb_mutex_impl_unlock (&m); }
  void fini ()   { hb_mutex_impl_finish (&m); }
};

struct hb_lock_t
{
  hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
  ~hb_lock_t () { mutex.unlock (); }
  private:
  hb_mutex_t &mutex;
};

#endif /* HB_MUTEX_HH */

repo_language: C

mime_type: text/x-c


text:
/*
 * Copyright © 2018 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_VORG_TABLE_HH
#define HB_OT_VORG_TABLE_HH

#include "hb-open-type.hh"

/*
 * VORG -- Vertical Origin Table
 * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg
 */
#define HB_OT_TAG_VORG HB_TAG('V','O','R','G')

namespace OT {

struct VertOriginMetric
{
  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }

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

  public:
  HBGlyphID	glyph;
  FWORD		vertOriginY;

  public:
  DEFINE_SIZE_STATIC (4);
};

struct VORG
{
  static constexpr hb_tag_t tableTag = HB_OT_TAG_VORG;

  bool has_data () const { return version.to_int (); }

  int get_y_origin (hb_codepoint_t glyph) const
  {
    unsigned int i;
    if (!vertYOrigins.bfind (glyph, &i))
      return defaultVertOriginY;
    return vertYOrigins[i].vertOriginY;
  }

  template <typename Iterator,
	    hb_requires (hb_is_iterator (Iterator))>
  void serialize (hb_serialize_context_t *c,
		  Iterator it,
		  FWORD defaultVertOriginY)
  {

    if (unlikely (!c->extend_min ((*this))))  return;

    this->version.major = 1;
    this->version.minor = 0;

    this->defaultVertOriginY = defaultVertOriginY;
    this->vertYOrigins.len = it.len ();

    c->copy_all (it);
  }

  bool subset (hb_subset_context_t *c) const
  {
    TRACE_SUBSET (this);
    VORG *vorg_prime = c->serializer->start_embed<VORG> ();
    if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false);

    auto it =
    + vertYOrigins.as_array ()
    | hb_filter (c->plan->glyphset (), &VertOriginMetric::glyph)
    | hb_map ([&] (const VertOriginMetric& _)
	      {
		hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID;
		c->plan->new_gid_for_old_gid (_.glyph, &new_glyph);

		VertOriginMetric metric;
		metric.glyph = new_glyph;
		metric.vertOriginY = _.vertOriginY;
		return metric;
	      })
    ;

    /* serialize the new table */
    vorg_prime->serialize (c->serializer, it, defaultVertOriginY);
    return_trace (true);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  version.major == 1 &&
		  vertYOrigins.sanitize (c));
  }

  protected:
  FixedVersion<>version;	/* Version of VORG table. Set to 0x00010000u. */
  FWORD		defaultVertOriginY;
				/* The default vertical origin. */
  SortedArrayOf<VertOriginMetric>
		vertYOrigins;	/* The array of vertical origins. */

  public:
  DEFINE_SIZE_ARRAY(8, vertYOrigins);
};
} /* namespace OT */

#endif /* HB_OT_VORG_TABLE_HH */


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

#ifndef HB_NUMBER_PARSER_HH
#define HB_NUMBER_PARSER_HH

#include "hb.hh"

%%{

machine double_parser;
alphtype unsigned char;
write data;

action see_neg { neg = true; }
action see_exp_neg { exp_neg = true; }

action add_int  {
	value = value * 10. + (fc - '0');
}
action add_frac {
	if (likely (frac <= MAX_FRACT / 10))
	{
	  frac = frac * 10. + (fc - '0');
	  ++frac_count;
	}
}
action add_exp  {
	if (likely (exp * 10 + (fc - '0') <= MAX_EXP))
	  exp = exp * 10 + (fc - '0');
	else
	  exp_overflow = true;
}

num = [0-9]+;

main := (
	(
		(('+'|'-'@see_neg)? num @add_int) ('.' num @add_frac)?
		|
		(('+'|'-'@see_neg)? '.' num @add_frac)
	)
	(('e'|'E') (('+'|'-'@see_exp_neg)? num @add_exp))?
);

}%%

/* Works only for n < 512 */
static inline double
_pow10 (unsigned exponent)
{
  static const double _powers_of_10[] =
  {
    1.0e+256,
    1.0e+128,
    1.0e+64,
    1.0e+32,
    1.0e+16,
    1.0e+8,
    10000.,
    100.,
    10.
  };
  unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
  double result = 1;
  for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
    if (exponent & mask) result *= *power;
  return result;
}

/* a variant of strtod that also gets end of buffer in its second argument */
static inline double
strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
{
  double value = 0;
  double frac = 0;
  double frac_count = 0;
  unsigned exp = 0;
  bool neg = false, exp_neg = false, exp_overflow = false;
  const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
  const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */

  const char *pe = *end_ptr;
  while (p < pe && ISSPACE (*p))
    p++;

  int cs;
  %%{
    write init;
    write exec;
  }%%

  *end_ptr = p;

  if (frac_count) value += frac / _pow10 (frac_count);
  if (neg) value *= -1.;

  if (unlikely (exp_overflow))
  {
    if (value == 0) return value;
    if (exp_neg)    return neg ? -DBL_MIN : DBL_MIN;
    else            return neg ? -DBL_MAX : DBL_MAX;
  }

  if (exp)
  {
    if (exp_neg) value /= _pow10 (exp);
    else         value *= _pow10 (exp);
  }

  return value;
}

#endif /* HB_NUMBER_PARSER_HH */


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

#ifndef HB_AAT_H_IN
#error "Include <hb-aat.h> instead."
#endif

#ifndef HB_AAT_LAYOUT_H
#define HB_AAT_LAYOUT_H

#include "hb.h"

#include "hb-ot.h"

HB_BEGIN_DECLS

/**
 * hb_aat_layout_feature_type_t:
 *
 *
 * Since: 2.2.0
 */
typedef enum
{
  HB_AAT_LAYOUT_FEATURE_TYPE_INVALID				= 0xFFFF,

  HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC			= 0,
  HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES				= 1,
  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION			= 2,
  HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE			= 3,
  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION		= 4,
  HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT		= 5,
  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING			= 6,
  HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE			= 8,
  HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE			= 9,
  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION			= 10,
  HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS				= 11,
  HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE	= 13,
  HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS			= 14,
  HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS		= 15,
  HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE			= 16,
  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES		= 17,
  HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE		= 18,
  HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS			= 19,
  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE			= 20,
  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE			= 21,
  HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING			= 22,
  HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION			= 23,
  HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE			= 24,
  HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE			= 25,
  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE		= 26,
  HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE		= 27,
  HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA				= 28,
  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE	= 29,
  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE	= 30,
  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE	= 31,
  HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN			= 32,
  HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT		= 33,
  HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA			= 34,
  HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES		= 35,
  HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES		= 36,
  HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE				= 37,
  HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE				= 38,
  HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE			= 39,
  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE		= 103,

  _HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_type_t;

/**
 * hb_aat_layout_feature_selector_t:
 *
 *
 * Since: 2.2.0
 */
typedef enum
{
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID			= 0xFFFF,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF		= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON			= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF			= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF		= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON		= 10,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF	= 11,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON		= 12,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF		= 13,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON	= 14,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF	= 15,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON		= 16,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF		= 17,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON	= 18,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF	= 19,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON	= 20,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF	= 21,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED			= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE			= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE		= 0, /* deprecated */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS			= 1, /* deprecated */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE			= 2, /* deprecated */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS			= 3, /* deprecated */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS			= 4, /* deprecated */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS	= 5, /* deprecated */

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF	= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF	= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS		= 3,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON	= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF	= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON		= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF		= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF		= 9,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS		= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS			= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS			= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS			= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS		= 4,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS			= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS		= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF		= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON		= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF		= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF		= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON		= 10,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF	= 11,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON	= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF	= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON	= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF	= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON			= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF			= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON		= 10,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF		= 11,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS			= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS			= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS			= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS			= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS			= 6,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES			= 0,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1			= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2			= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3			= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4			= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5			= 4,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT			= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT			= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS			= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS			= 5,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO		= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE		= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE		= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS		= 10,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS		= 11,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS		= 12,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS			= 13,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS	= 14,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS		= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT		= 6,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA	= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA	= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE	= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO	= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE	= 9,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION			= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION			= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION	= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION		= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION	= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION	= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION= 10,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA		= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS		= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON	= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF	= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON	= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF	= 5,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA			= 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF instead */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA			= 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON instead */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON			= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF			= 3,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE		= 5,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE		= 5,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE	= 1,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN		= 0,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF instead */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN		= 1,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON instead */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF		= 3,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON	= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF	= 3,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF	= 3,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON		= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF		= 5,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON		= 6,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF	= 7,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON		= 8,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF		= 9,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON		= 10,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF		= 11,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON		= 12,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF		= 13,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON		= 14,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF	= 15,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON		= 16,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF	= 17,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON		= 18,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF		= 19,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON		= 20,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF		= 21,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON	= 22,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF	= 23,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON	= 24,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF	= 25,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON	= 26,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF	= 27,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON	= 28,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF	= 29,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON	= 30,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF	= 31,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON	= 32,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF	= 33,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON	= 34,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF	= 35,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON	= 36,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF	= 37,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON	= 38,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF	= 39,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON	= 40,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF	= 41,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON	= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF	= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF		= 3,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON	= 4,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF= 5,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS		= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS		= 2,

  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE */
  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN		= 0,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN		= 1,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN		= 2,
  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN		= 3,

  _HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_selector_t;

HB_EXTERN unsigned int
hb_aat_layout_get_feature_types (hb_face_t                    *face,
				 unsigned int                  start_offset,
				 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
				 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */);

HB_EXTERN hb_ot_name_id_t
hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
					hb_aat_layout_feature_type_t  feature_type);

typedef struct hb_aat_layout_feature_selector_info_t
{
  hb_ot_name_id_t			name_id;
  hb_aat_layout_feature_selector_t	enable;
  hb_aat_layout_feature_selector_t	disable;
  /*< private >*/
  unsigned int				reserved;
} hb_aat_layout_feature_selector_info_t;

#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX		0xFFFFu

HB_EXTERN unsigned int
hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
					       hb_aat_layout_feature_type_t           feature_type,
					       unsigned int                           start_offset,
					       unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
					       hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
					       unsigned int                          *default_index   /* OUT.     May be NULL. */);

/*
 * morx/mort
 */

HB_EXTERN hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face);

/*
 * kerx
 */

HB_EXTERN hb_bool_t
hb_aat_layout_has_positioning (hb_face_t *face);

/*
 * trak
 */

HB_EXTERN hb_bool_t
hb_aat_layout_has_tracking (hb_face_t *face);

HB_END_DECLS

#endif /* HB_AAT_LAYOUT_H */


text:
# Process this file with automake to produce Makefile.in

NULL =
SUBDIRS =
DIST_SUBDIRS =
BUILT_SOURCES =
EXTRA_DIST =
CLEANFILES =
DISTCLEANFILES =
MAINTAINERCLEANFILES =
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
TESTS =
check_PROGRAMS =

EXTRA_DIST += harfbuzz.cc
EXTRA_DIST += meson.build
EXTRA_DIST += fix_get_types.py

# Convenience targets:
lib: $(BUILT_SOURCES) libharfbuzz.la
libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
tiny:
	$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Os -DHB_TINY $(CPPFLAGS)" libs
tinyz:
	$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Oz -DHB_TINY $(CPPFLAGS)" libs

lib_LTLIBRARIES = libharfbuzz.la

include Makefile.sources

HBCFLAGS =
HBLIBS =
HBNONPCLIBS =
HBDEPS =
HBSOURCES =  $(HB_BASE_sources)
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
HBHEADERS = $(HB_BASE_headers)

if HAVE_PTHREAD
HBCFLAGS += $(PTHREAD_CFLAGS)
HBNONPCLIBS += $(PTHREAD_LIBS)
endif

if HAVE_GLIB
HBCFLAGS += $(GLIB_CFLAGS)
HBLIBS   += $(GLIB_LIBS)
HBDEPS   += $(GLIB_DEPS)
HBSOURCES += $(HB_GLIB_sources)
HBHEADERS += $(HB_GLIB_headers)
endif

if HAVE_FREETYPE
HBCFLAGS += $(FREETYPE_CFLAGS)
HBLIBS   += $(FREETYPE_LIBS)
HBDEPS   += $(FREETYPE_DEPS)
HBSOURCES += $(HB_FT_sources)
HBHEADERS += $(HB_FT_headers)
endif

if HAVE_GRAPHITE2
HBCFLAGS += $(GRAPHITE2_CFLAGS)
HBLIBS   += $(GRAPHITE2_LIBS)
HBDEPS   += $(GRAPHITE2_DEPS)
HBSOURCES += $(HB_GRAPHITE2_sources)
HBHEADERS += $(HB_GRAPHITE2_headers)
endif

if HAVE_UNISCRIBE
HBCFLAGS += $(UNISCRIBE_CFLAGS)
HBNONPCLIBS += $(UNISCRIBE_LIBS)
HBSOURCES += $(HB_UNISCRIBE_sources)
HBHEADERS += $(HB_UNISCRIBE_headers)
endif

if HAVE_DIRECTWRITE
HBCFLAGS += $(DIRECTWRITE_CXXFLAGS)
HBNONPCLIBS += $(DIRECTWRITE_LIBS)
HBSOURCES += $(HB_DIRECTWRITE_sources)
HBHEADERS += $(HB_DIRECTWRITE_headers)
endif

if HAVE_GDI
HBCFLAGS += $(GDI_CXXFLAGS)
HBNONPCLIBS += $(GDI_LIBS)
HBSOURCES += $(HB_GDI_sources)
HBHEADERS += $(HB_GDI_headers)
endif

if HAVE_CORETEXT
HBCFLAGS += $(CORETEXT_CFLAGS)
HBNONPCLIBS += $(CORETEXT_LIBS)
HBSOURCES += $(HB_CORETEXT_sources)
HBHEADERS += $(HB_CORETEXT_headers)
endif

BUILT_SOURCES += \
	hb-version.h

$(srcdir)/hb-version.h: hb-version.h.in $(top_srcdir)/configure.ac
	$(AM_V_GEN) $(SED) \
		-e 's/[@]HB_VERSION_MAJOR@/$(HB_VERSION_MAJOR)/' \
		-e 's/[@]HB_VERSION_MINOR@/$(HB_VERSION_MINOR)/' \
		-e 's/[@]HB_VERSION_MICRO@/$(HB_VERSION_MICRO)/' \
		-e 's/[@]HB_VERSION@/$(HB_VERSION)/' \
		"$<" > "$@" || ($(RM) "$@"; false)

# Put the library together

HBLIBS += $(HBNONPCLIBS)

if OS_WIN32
export_symbols = -export-symbols harfbuzz.def
harfbuzz_def_dependency = harfbuzz.def
export_symbols_subset = -export-symbols harfbuzz-subset.def
harfbuzz_subset_def_dependency = harfbuzz-subset.def
export_symbols_icu = -export-symbols harfbuzz-icu.def
harfbuzz_icu_def_dependency = harfbuzz-icu.def
export_symbols_gobject = -export-symbols harfbuzz-gobject.def
harfbuzz_gobject_def_dependency = harfbuzz-gobject.def
chosen_linker = $(CXXLINK)
else
if WITH_LIBSTDCXX
chosen_linker = $(CXXLINK)
else
if HAVE_GCC
# Use a C linker for GCC, not C++; Don't link to libstdc++
chosen_linker = $(LINK)
else
chosen_linker = $(CXXLINK)
endif
endif
endif

@CODE_COVERAGE_RULES@

base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols) $(CODE_COVERAGE_LDFLAGS)
libharfbuzz_la_LIBADD = $(HBLIBS)
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
pkginclude_HEADERS = $(HBHEADERS)
nodist_pkginclude_HEADERS =
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = harfbuzz.pc
cmakedir = $(libdir)/cmake/harfbuzz
cmake_DATA = harfbuzz-config.cmake
EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in

lib_LTLIBRARIES += libharfbuzz-subset.la
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) $(CODE_COVERAGE_LDFLAGS)
libharfbuzz_subset_la_LIBADD = libharfbuzz.la
EXTRA_libharfbuzz_subset_la_DEPENDENCIES = $(harfbuzz_subset_def_dependency)
pkginclude_HEADERS += $(HB_SUBSET_headers)
pkgconfig_DATA += harfbuzz-subset.pc
EXTRA_DIST += harfbuzz-subset.pc.in

if HAVE_ICU
if HAVE_ICU_BUILTIN
HBCFLAGS += $(ICU_CFLAGS)
HBLIBS += $(ICU_LIBS)
HBSOURCES += $(HB_ICU_sources)
HBHEADERS += $(HB_ICU_headers)
else
lib_LTLIBRARIES += libharfbuzz-icu.la
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu) $(CODE_COVERAGE_LDFLAGS)
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
pkginclude_HEADERS += $(HB_ICU_headers)
pkgconfig_DATA += harfbuzz-icu.pc
endif
endif
EXTRA_DIST += harfbuzz-icu.pc.in

if HAVE_GOBJECT
lib_LTLIBRARIES += libharfbuzz-gobject.la
libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS)
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources)
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources)
libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(GOBJECT_CFLAGS) $(CODE_COVERAGE_CFLAGS)
libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags) $(CODE_COVERAGE_LDFLAGS)
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency)
pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers)
nodist_pkginclude_HEADERS += $(HB_GOBJECT_NODIST_headers)
pkgconfig_DATA += harfbuzz-gobject.pc

BUILT_SOURCES += \
	$(HB_GOBJECT_ENUM_sources) \
	$(HB_GOBJECT_ENUM_headers) \
	$(NULL)
DISTCLEANFILES += \
	$(HB_GOBJECT_ENUM_sources) \
	$(HB_GOBJECT_ENUM_headers) \
	$(NULL)
hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
	$(AM_V_GEN) PYTHONIOENCODING=UTF-8 $(GLIB_MKENUMS) \
		--identifier-prefix hb_ --symbol-prefix hb_gobject \
		--template $^ | \
	sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
	|| ($(RM) "$@"; false)
endif
EXTRA_DIST += \
	harfbuzz-gobject.pc.in \
	hb-gobject-enums.cc.tmpl \
	hb-gobject-enums.h.tmpl \
	$(NULL)

%.pc: %.pc.in $(top_builddir)/config.status
	$(AM_V_GEN) \
	$(SED)	-e 's@%prefix%@$(prefix)@g' \
		-e 's@%exec_prefix%@$(exec_prefix)@g' \
		-e 's@%libdir%@$(libdir)@g' \
		-e 's@%includedir%@$(includedir)@g' \
		-e 's@%libs_private%@$(HBNONPCLIBS)@g' \
		-e 's@%requires_private%@$(HBDEPS)@g' \
		-e 's@%VERSION%@$(VERSION)@g' \
	"$<" > "$@" \
	|| ($(RM) "$@"; false)

CLEANFILES += $(pkgconfig_DATA)

DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated-symbols.txt
if HAVE_GOBJECT
DEF_FILES += harfbuzz-gobject.def
endif
check: $(DEF_FILES) # For check-symbols.sh
CLEANFILES += $(DEF_FILES)
harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-subset.def: $(HB_SUBSET_headers)
	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-icu.def: $(HB_ICU_headers)
	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
	$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-deprecated-symbols.txt: $(srcdir)/hb-deprecated.h
	$(AM_V_GEN) PLAIN_LIST=1 $(srcdir)/gen-def.py "$@" $^

GENERATORS = \
	gen-arabic-table.py \
	gen-def.py \
	gen-emoji-table.py \
	gen-indic-table.py \
	gen-os2-unicode-ranges.py \
	gen-tag-table.py \
	gen-ucd-table.py \
	gen-use-table.py \
	gen-vowel-constraints.py \
	$(NULL)
EXTRA_DIST += $(GENERATORS)

unicode-tables: \
	arabic-table \
	emoji-table \
	indic-table \
	tag-table \
	ucd-table \
	use-table \
	emoji-table \
	$(NULL)

arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
	|| ($(RM) $(srcdir)/hb-ot-shape-complex-arabic-table.hh; false)
emoji-table: gen-emoji-table.py emoji-data.txt
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
	|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
	|| ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
tag-table: gen-tag-table.py languagetags language-subtag-registry
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
	|| ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ucd-table.hh \
	|| ($(RM) $(srcdir)/hb-ucd-table.hh; false)
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
	|| ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
vowel-constraints: gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
	$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
	|| ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)

built-sources: $(BUILT_SOURCES)

.PHONY: unicode-tables arabic-table indic-table tag-table use-table vowel-constraints emoji-table built-sources

RAGEL_GENERATED = \
	$(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \
	$(NULL)
BUILT_SOURCES += $(RAGEL_GENERATED)
EXTRA_DIST += \
	$(HB_BASE_RAGEL_sources) \
	$(NULL)
# We decided to add ragel-generated files to git...
#MAINTAINERCLEANFILES += $(RAGEL_GENERATED)
$(srcdir)/%.hh: $(srcdir)/%.rl
	$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
	|| ($(RM) "$@"; false)

harfbuzz.cc: Makefile.sources
	$(AM_V_GEN) \
	for f in \
		$(HB_BASE_sources) \
		$(HB_GLIB_sources) \
		$(HB_FT_sources) \
		$(HB_GRAPHITE2_sources) \
		$(HB_UNISCRIBE_sources) \
		$(HB_GDI_sources) \
		$(HB_DIRECTWRITE_sources) \
		$(HB_CORETEXT_sources) \
		; do echo '#include "'$$f'"'; done | \
	grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
	|| ($(RM) $(srcdir)/harfbuzz.cc; false)
BUILT_SOURCES += harfbuzz.cc

noinst_PROGRAMS = \
	main \
	test \
	test-buffer-serialize \
	test-ot-meta \
	test-ot-name \
	test-ot-glyphname \
	test-gpos-size-params \
	test-gsub-would-substitute \
	$(NULL)
bin_PROGRAMS =

main_SOURCES = main.cc
main_CPPFLAGS = $(HBCFLAGS)
main_LDADD = libharfbuzz.la $(HBLIBS)

test_SOURCES = test.cc
test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)

test_buffer_serialize_SOURCES = test-buffer-serialize.cc
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)

test_ot_meta_SOURCES = test-ot-meta.cc
test_ot_meta_CPPFLAGS = $(HBCFLAGS)
test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)

test_ot_name_SOURCES = test-ot-name.cc
test_ot_name_CPPFLAGS = $(HBCFLAGS)
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)

test_ot_glyphname_SOURCES = test-ot-glyphname.cc
test_ot_glyphname_CPPFLAGS = $(HBCFLAGS)
test_ot_glyphname_LDADD = libharfbuzz.la $(HBLIBS)

test_gpos_size_params_SOURCES = test-gpos-size-params.cc
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)

test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)

check_PROGRAMS += \
	dump-indic-data \
	dump-khmer-data \
	dump-myanmar-data \
	dump-use-data \
	$(NULL)
dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
dump_indic_data_CPPFLAGS = $(HBCFLAGS)
dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
dump_khmer_data_SOURCES = dump-khmer-data.cc hb-ot-shape-complex-indic-table.cc
dump_khmer_data_CPPFLAGS = $(HBCFLAGS)
dump_khmer_data_LDADD = libharfbuzz.la $(HBLIBS)
dump_myanmar_data_SOURCES = dump-myanmar-data.cc hb-ot-shape-complex-indic-table.cc
dump_myanmar_data_CPPFLAGS = $(HBCFLAGS)
dump_myanmar_data_LDADD = libharfbuzz.la $(HBLIBS)
dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
dump_use_data_CPPFLAGS = $(HBCFLAGS)
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)

COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
check_PROGRAMS += $(COMPILED_TESTS)
TESTS += $(COMPILED_TESTS)

test_algs_SOURCES = test-algs.cc hb-static.cc
test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_algs_LDADD = $(COMPILED_TESTS_LDADD)

test_array_SOURCES = test-array.cc
test_array_CPPFLAGS = $(HBCFLAGS)
test_array_LDADD = libharfbuzz.la $(HBLIBS)

test_iter_SOURCES = test-iter.cc hb-static.cc
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_iter_LDADD = $(COMPILED_TESTS_LDADD)

test_meta_SOURCES = test-meta.cc hb-static.cc
test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_meta_LDADD = $(COMPILED_TESTS_LDADD)

test_number_SOURCES = test-number.cc hb-number.cc
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_number_LDADD = $(COMPILED_TESTS_LDADD)

test_ot_tag_SOURCES = hb-ot-tag.cc
test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)

test_unicode_ranges_SOURCES = test-unicode-ranges.cc
test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)

test_bimap_SOURCES = test-bimap.cc hb-static.cc
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)

dist_check_SCRIPTS = \
	check-c-linkage-decls.sh \
	check-externs.sh \
	check-header-guards.sh \
	check-includes.sh \
	check-static-inits.sh \
	check-symbols.sh \
	$(NULL)
TESTS += $(dist_check_SCRIPTS)

if !WITH_LIBSTDCXX
dist_check_SCRIPTS += \
	check-libstdc++.sh \
	$(NULL)
endif

TESTS_ENVIRONMENT = \
	srcdir="$(srcdir)" \
	builddir="$(builddir)" \
	MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
	HBSOURCES="$(HBSOURCES)" \
	HBHEADERS="$(HBHEADERS)" \
	$(NULL)

if HAVE_INTROSPECTION

-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?!
INTROSPECTION_SCANNER_ARGS = \
	-I$(srcdir) \
	--warn-all --verbose \
	--namespace=HarfBuzz \
	--nsversion=0.0 \
	--symbol-prefix=hb \
	--symbol-prefix=hb_gobject \
	--identifier-prefix=hb_ \
	--pkg-export=harfbuzz-gobject \
	--c-include=hb-gobject.h
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
INTROSPECTION_SCANNER_ENV = CC="$(CC)"

HarfBuzz-0.0.gir: libharfbuzz.la libharfbuzz-gobject.la
HarfBuzz_0_0_gir_INCLUDES = GObject-2.0
HarfBuzz_0_0_gir_CFLAGS = \
	$(INCLUDES) \
	$(HBCFLAGS) \
	-DHB_H \
	-DHB_H_IN \
	-DHB_OT_H \
	-DHB_OT_H_IN \
	-DHB_AAT_H \
	-DHB_AAT_H_IN \
	-DHB_GOBJECT_H \
	-DHB_GOBJECT_H_IN \
	-DHAVE_GOBJECT \
	-DHB_EXTERN= \
	$(NULL)
HarfBuzz_0_0_gir_LIBS = \
	libharfbuzz.la \
	libharfbuzz-gobject.la \
	$(NULL)
HarfBuzz_0_0_gir_FILES = \
	$(HBHEADERS) \
	$(HBSOURCES) \
	$(HB_GOBJECT_sources) \
	$(HB_GOBJECT_headers) \
	$(NULL)

girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)

typelibdir = $(libdir)/girepository-1.0
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)

CLEANFILES += $(gir_DATA) $(typelib_DATA)

endif

-include $(top_srcdir)/git.mk


text:
/*
 * Copyright © 1998-2004  David Turner and Werner Lemberg
 * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
 * 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.
 *
 * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_BUFFER_HH
#define HB_BUFFER_HH

#include "hb.hh"
#include "hb-unicode.hh"

#ifndef HB_BUFFER_MAX_LEN_FACTOR
#define HB_BUFFER_MAX_LEN_FACTOR 32
#endif
#ifndef HB_BUFFER_MAX_LEN_MIN
#define HB_BUFFER_MAX_LEN_MIN 8192
#endif
#ifndef HB_BUFFER_MAX_LEN_DEFAULT
#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
#endif

#ifndef HB_BUFFER_MAX_OPS_FACTOR
#define HB_BUFFER_MAX_OPS_FACTOR 64
#endif
#ifndef HB_BUFFER_MAX_OPS_MIN
#define HB_BUFFER_MAX_OPS_MIN 1024
#endif
#ifndef HB_BUFFER_MAX_OPS_DEFAULT
#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
#endif

static_assert ((sizeof (hb_glyph_info_t) == 20), "");
static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");

HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);

enum hb_buffer_scratch_flags_t {
  HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII			= 0x00000001u,
  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK		= 0x00000010u,
  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ			= 0x00000020u,

  /* Reserved for complex shapers' internal use. */
  HB_BUFFER_SCRATCH_FLAG_COMPLEX0			= 0x01000000u,
  HB_BUFFER_SCRATCH_FLAG_COMPLEX1			= 0x02000000u,
  HB_BUFFER_SCRATCH_FLAG_COMPLEX2			= 0x04000000u,
  HB_BUFFER_SCRATCH_FLAG_COMPLEX3			= 0x08000000u,
};
HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);

/*
 * hb_buffer_t
 */

struct hb_buffer_t
{
  hb_object_header_t header;

  /* Information about how the text in the buffer should be treated */
  hb_unicode_funcs_t *unicode; /* Unicode functions */
  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
  hb_buffer_cluster_level_t cluster_level;
  hb_codepoint_t replacement; /* U+FFFD or something else. */
  hb_codepoint_t invisible; /* 0 or something else. */
  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
  unsigned int max_len; /* Maximum allowed len. */
  int max_ops; /* Maximum allowed operations. */

  /* Buffer contents */
  hb_buffer_content_type_t content_type;
  hb_segment_properties_t props; /* Script, language, direction */

  bool successful; /* Allocations successful */
  bool have_output; /* Whether we have an output buffer going on */
  bool have_positions; /* Whether we have positions */

  unsigned int idx; /* Cursor into ->info and ->pos arrays */
  unsigned int len; /* Length of ->info and ->pos arrays */
  unsigned int out_len; /* Length of ->out array if have_output */

  unsigned int allocated; /* Length of allocated arrays */
  hb_glyph_info_t     *info;
  hb_glyph_info_t     *out_info;
  hb_glyph_position_t *pos;

  unsigned int serial;

  /* Text before / after the main buffer contents.
   * Always in Unicode, and ordered outward.
   * Index 0 is for "pre-context", 1 for "post-context". */
  static constexpr unsigned CONTEXT_LENGTH = 5u;
  hb_codepoint_t context[2][CONTEXT_LENGTH];
  unsigned int context_len[2];

  /* Debugging API */
#ifndef HB_NO_BUFFER_MESSAGE
  hb_buffer_message_func_t message_func;
  void *message_data;
  hb_destroy_func_t message_destroy;
#endif

  /* Internal debugging. */
  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
#ifndef HB_NDEBUG
  uint8_t allocated_var_bits;
#endif

  /* Methods */

  bool in_error () const { return !successful; }

  void allocate_var (unsigned int start, unsigned int count)
  {
#ifndef HB_NDEBUG
    unsigned int end = start + count;
    assert (end <= 8);
    unsigned int bits = (1u<<end) - (1u<<start);
    assert (0 == (allocated_var_bits & bits));
    allocated_var_bits |= bits;
#endif
  }
  void deallocate_var (unsigned int start, unsigned int count)
  {
#ifndef HB_NDEBUG
    unsigned int end = start + count;
    assert (end <= 8);
    unsigned int bits = (1u<<end) - (1u<<start);
    assert (bits == (allocated_var_bits & bits));
    allocated_var_bits &= ~bits;
#endif
  }
  void assert_var (unsigned int start, unsigned int count)
  {
#ifndef HB_NDEBUG
    unsigned int end = start + count;
    assert (end <= 8);
    unsigned int bits = (1u<<end) - (1u<<start);
    assert (bits == (allocated_var_bits & bits));
#endif
  }
  void deallocate_var_all ()
  {
#ifndef HB_NDEBUG
    allocated_var_bits = 0;
#endif
  }

  hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
  hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }

  hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
  hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }

  hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
  hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }

  bool has_separate_output () const { return info != out_info; }

  HB_INTERNAL void reset ();
  HB_INTERNAL void clear ();

  unsigned int backtrack_len () const { return have_output? out_len : idx; }
  unsigned int lookahead_len () const { return len - idx; }
  unsigned int next_serial () { return serial++; }

  HB_INTERNAL void add (hb_codepoint_t  codepoint,
			unsigned int    cluster);
  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);

  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
  HB_INTERNAL void reverse ();
  HB_INTERNAL void reverse_clusters ();
  HB_INTERNAL void guess_segment_properties ();

  HB_INTERNAL void swap_buffers ();
  HB_INTERNAL void remove_output ();
  HB_INTERNAL void clear_output ();
  HB_INTERNAL void clear_positions ();

  HB_INTERNAL void replace_glyphs (unsigned int num_in,
				   unsigned int num_out,
				   const hb_codepoint_t *glyph_data);

  void replace_glyph (hb_codepoint_t glyph_index)
  {
    if (unlikely (out_info != info || out_len != idx)) {
      if (unlikely (!make_room_for (1, 1))) return;
      out_info[out_len] = info[idx];
    }
    out_info[out_len].codepoint = glyph_index;

    idx++;
    out_len++;
  }
  /* Makes a copy of the glyph at idx to output and replace glyph_index */
  hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
  {
    if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t);

    if (unlikely (idx == len && !out_len))
      return Crap (hb_glyph_info_t);

    out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
    out_info[out_len].codepoint = glyph_index;

    out_len++;

    return out_info[out_len - 1];
  }
  void output_info (const hb_glyph_info_t &glyph_info)
  {
    if (unlikely (!make_room_for (0, 1))) return;

    out_info[out_len] = glyph_info;

    out_len++;
  }
  /* Copies glyph at idx to output but doesn't advance idx */
  void copy_glyph ()
  {
    if (unlikely (!make_room_for (0, 1))) return;

    out_info[out_len] = info[idx];

    out_len++;
  }
  /* Copies glyph at idx to output and advance idx.
   * If there's no output, just advance idx. */
  void
  next_glyph ()
  {
    if (have_output)
    {
      if (out_info != info || out_len != idx)
      {
	if (unlikely (!make_room_for (1, 1))) return;
	out_info[out_len] = info[idx];
      }
      out_len++;
    }

    idx++;
  }
  /* Copies n glyphs at idx to output and advance idx.
   * If there's no output, just advance idx. */
  void
  next_glyphs (unsigned int n)
  {
    if (have_output)
    {
      if (out_info != info || out_len != idx)
      {
	if (unlikely (!make_room_for (n, n))) return;
	memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
      }
      out_len += n;
    }

    idx += n;
  }
  /* Advance idx without copying to output. */
  void skip_glyph () { idx++; }
  void reset_masks (hb_mask_t mask)
  {
    for (unsigned int j = 0; j < len; j++)
      info[j].mask = mask;
  }
  void add_masks (hb_mask_t mask)
  {
    for (unsigned int j = 0; j < len; j++)
      info[j].mask |= mask;
  }
  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
			      unsigned int cluster_start, unsigned int cluster_end);

  void merge_clusters (unsigned int start, unsigned int end)
  {
    if (end - start < 2)
      return;
    merge_clusters_impl (start, end);
  }
  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
  /* Merge clusters for deleting current glyph, and skip it. */
  HB_INTERNAL void delete_glyph ();

  void unsafe_to_break (unsigned int start,
			       unsigned int end)
  {
    if (end - start < 2)
      return;
    unsafe_to_break_impl (start, end);
  }
  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);

  /* Internal methods */
  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */

  HB_INTERNAL bool enlarge (unsigned int size);

  bool ensure (unsigned int size)
  { return likely (!size || size < allocated) ? true : enlarge (size); }

  bool ensure_inplace (unsigned int size)
  { return likely (!size || size < allocated); }

  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
  HB_INTERNAL bool shift_forward (unsigned int count);

  typedef long scratch_buffer_t;
  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);

  void clear_context (unsigned int side) { context_len[side] = 0; }

  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));

  bool messaging ()
  {
#ifdef HB_NO_BUFFER_MESSAGE
    return false;
#else
    return unlikely (message_func);
#endif
  }
  bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
  {
#ifdef HB_NO_BUFFER_MESSAGE
   return true;
#else
    if (!messaging ())
      return true;
    va_list ap;
    va_start (ap, fmt);
    bool ret = message_impl (font, fmt, ap);
    va_end (ap);
    return ret;
#endif
  }
  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);

  static void
  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
  {
    if (inf.cluster != cluster)
    {
      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
	inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
      else
	inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    }
    inf.cluster = cluster;
  }

  unsigned int
  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
				     unsigned int start, unsigned int end,
				     unsigned int cluster) const
  {
    for (unsigned int i = start; i < end; i++)
      cluster = hb_min (cluster, infos[i].cluster);
    return cluster;
  }
  void
  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
			     unsigned int start, unsigned int end,
			     unsigned int cluster)
  {
    for (unsigned int i = start; i < end; i++)
      if (cluster != infos[i].cluster)
      {
	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
	infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
      }
  }

  void unsafe_to_break_all () { unsafe_to_break_impl (0, len); }
  void safe_to_break_all ()
  {
    for (unsigned int i = 0; i < len; i++)
      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
  }
};
DECLARE_NULL_INSTANCE (hb_buffer_t);

/* Loop over clusters. Duplicated in foreach_syllable(). */
#define foreach_cluster(buffer, start, end) \
  for (unsigned int \
       _count = buffer->len, \
       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
       start < _count; \
       start = end, end = _next_cluster (buffer, start))

static inline unsigned int
_next_cluster (hb_buffer_t *buffer, unsigned int start)
{
  hb_glyph_info_t *info = buffer->info;
  unsigned int count = buffer->len;

  unsigned int cluster = info[start].cluster;
  while (++start < count && cluster == info[start].cluster)
    ;

  return start;
}

#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
	   sizeof (b->info[0].var))
#define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
#define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
#define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())

#endif /* HB_BUFFER_HH */


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

#ifndef HB_OPEN_FILE_HH
#define HB_OPEN_FILE_HH

#include "hb-open-type.hh"
#include "hb-ot-head-table.hh"

namespace OT {

/*
 *
 * The OpenType Font File
 *
 */

/*
 * Organization of an OpenType Font
 */

struct OpenTypeFontFile;
struct OffsetTable;
struct TTCHeader;

typedef struct TableRecord
{
  int cmp (Tag t) const { return -t.cmp (tag); }

  HB_INTERNAL static int cmp (const void *pa, const void *pb)
  {
    const TableRecord *a = (const TableRecord *) pa;
    const TableRecord *b = (const TableRecord *) pb;
    return b->cmp (a->tag);
  }

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

  Tag		tag;		/* 4-byte identifier. */
  CheckSum	checkSum;	/* CheckSum for this table. */
  Offset32	offset;		/* Offset from beginning of TrueType font
				 * file. */
  HBUINT32	length;		/* Length of this table. */
  public:
  DEFINE_SIZE_STATIC (16);
} OpenTypeTable;

typedef struct OffsetTable
{
  friend struct OpenTypeFontFile;

  unsigned int get_table_count () const { return tables.len; }
  const TableRecord& get_table (unsigned int i) const
  { return tables[i]; }
  unsigned int get_table_tags (unsigned int  start_offset,
			       unsigned int *table_count, /* IN/OUT */
			       hb_tag_t     *table_tags /* OUT */) const
  {
    if (table_count)
    {
      if (start_offset >= tables.len)
	*table_count = 0;
      else
	*table_count = hb_min (*table_count, tables.len - start_offset);

      const TableRecord *sub_tables = tables.arrayZ + start_offset;
      unsigned int count = *table_count;
      for (unsigned int i = 0; i < count; i++)
	table_tags[i] = sub_tables[i].tag;
    }
    return tables.len;
  }
  bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
  {
    Tag t;
    t = tag;
    return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
  }
  const TableRecord& get_table_by_tag (hb_tag_t tag) const
  {
    unsigned int table_index;
    find_table_index (tag, &table_index);
    return get_table (table_index);
  }

  public:

  template <typename item_t>
  bool serialize (hb_serialize_context_t *c,
		  hb_tag_t sfnt_tag,
		  hb_array_t<item_t> items)
  {
    TRACE_SERIALIZE (this);
    /* Alloc 12 for the OTHeader. */
    if (unlikely (!c->extend_min (*this))) return_trace (false);
    /* Write sfntVersion (bytes 0..3). */
    sfnt_version = sfnt_tag;
    /* Take space for numTables, searchRange, entrySelector, RangeShift
     * and the TableRecords themselves.  */
    if (unlikely (!tables.serialize (c, items.length))) return_trace (false);

    const char *dir_end = (const char *) c->head;
    HBUINT32 *checksum_adjustment = nullptr;

    /* Write OffsetTables, alloc for and write actual table blobs. */
    for (unsigned int i = 0; i < tables.len; i++)
    {
      TableRecord &rec = tables.arrayZ[i];
      hb_blob_t *blob = items[i].blob;
      rec.tag = items[i].tag;
      rec.length = blob->length;
      rec.offset.serialize (c, this);

      /* Allocate room for the table and copy it. */
      char *start = (char *) c->allocate_size<void> (rec.length);
      if (unlikely (!start)) return false;

      if (likely (rec.length))
	memcpy (start, blob->data, rec.length);

      /* 4-byte alignment. */
      c->align (4);
      const char *end = (const char *) c->head;

      if (items[i].tag == HB_OT_TAG_head &&
	  (unsigned) (end - start) >= head::static_size)
      {
	head *h = (head *) start;
	checksum_adjustment = &h->checkSumAdjustment;
	*checksum_adjustment = 0;
      }

      rec.checkSum.set_for_data (start, end - start);
    }

    tables.qsort ();

    if (checksum_adjustment)
    {
      CheckSum checksum;

      /* The following line is a slower version of the following block. */
      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
      checksum.set_for_data (this, dir_end - (const char *) this);
      for (unsigned int i = 0; i < items.length; i++)
      {
	TableRecord &rec = tables.arrayZ[i];
	checksum = checksum + rec.checkSum;
      }

      *checksum_adjustment = 0xB1B0AFBAu - checksum;
    }

    return_trace (true);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) && tables.sanitize (c));
  }

  protected:
  Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
  BinSearchArrayOf<TableRecord>
		tables;
  public:
  DEFINE_SIZE_ARRAY (12, tables);
} OpenTypeFontFace;

/*
 * TrueType Collections
 */

struct TTCHeaderVersion1
{
  friend struct TTCHeader;

  unsigned int get_face_count () const { return table.len; }
  const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (table.sanitize (c, this));
  }

  protected:
  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
  FixedVersion<>version;	/* Version of the TTC Header (1.0),
				 * 0x00010000u */
  LArrayOf<LOffsetTo<OffsetTable>>
		table;		/* Array of offsets to the OffsetTable for each font
				 * from the beginning of the file */
  public:
  DEFINE_SIZE_ARRAY (12, table);
};

struct TTCHeader
{
  friend struct OpenTypeFontFile;

  private:

  unsigned int get_face_count () const
  {
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return u.version1.get_face_count ();
    default:return 0;
    }
  }
  const OpenTypeFontFace& get_face (unsigned int i) const
  {
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return u.version1.get_face (i);
    default:return Null (OpenTypeFontFace);
    }
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
    switch (u.header.version.major) {
    case 2: /* version 2 is compatible with version 1 */
    case 1: return_trace (u.version1.sanitize (c));
    default:return_trace (true);
    }
  }

  protected:
  union {
  struct {
  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
  FixedVersion<>version;	/* Version of the TTC Header (1.0 or 2.0),
				 * 0x00010000u or 0x00020000u */
  }			header;
  TTCHeaderVersion1	version1;
  } u;
};

/*
 * Mac Resource Fork
 *
 * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
 */

struct ResourceRecord
{
  const OpenTypeFontFace & get_face (const void *data_base) const
  { return * reinterpret_cast<const OpenTypeFontFace *> ((data_base+offset).arrayZ); }

  bool sanitize (hb_sanitize_context_t *c,
		 const void *data_base) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  offset.sanitize (c, data_base) &&
		  get_face (data_base).sanitize (c));
  }

  protected:
  HBUINT16	id;		/* Resource ID. */
  HBINT16	nameOffset;	/* Offset from beginning of resource name list
				 * to resource name, -1 means there is none. */
  HBUINT8	attrs;		/* Resource attributes */
  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
		offset;		/* Offset from beginning of data block to
				 * data for this resource */
  HBUINT32	reserved;	/* Reserved for handle to resource */
  public:
  DEFINE_SIZE_STATIC (12);
};

#define HB_TAG_sfnt HB_TAG ('s','f','n','t')

struct ResourceTypeRecord
{
  unsigned int get_resource_count () const
  { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }

  bool is_sfnt () const { return tag == HB_TAG_sfnt; }

  const ResourceRecord& get_resource_record (unsigned int i,
					     const void *type_base) const
  { return (type_base+resourcesZ).as_array (get_resource_count ())[i]; }

  bool sanitize (hb_sanitize_context_t *c,
		 const void *type_base,
		 const void *data_base) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  resourcesZ.sanitize (c, type_base,
				       get_resource_count (),
				       data_base));
  }

  protected:
  Tag		tag;		/* Resource type. */
  HBUINT16	resCountM1;	/* Number of resources minus 1. */
  NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
		resourcesZ;	/* Offset from beginning of resource type list
				 * to reference item list for this type. */
  public:
  DEFINE_SIZE_STATIC (8);
};

struct ResourceMap
{
  unsigned int get_face_count () const
  {
    unsigned int count = get_type_count ();
    for (unsigned int i = 0; i < count; i++)
    {
      const ResourceTypeRecord& type = get_type_record (i);
      if (type.is_sfnt ())
	return type.get_resource_count ();
    }
    return 0;
  }

  const OpenTypeFontFace& get_face (unsigned int idx,
				    const void *data_base) const
  {
    unsigned int count = get_type_count ();
    for (unsigned int i = 0; i < count; i++)
    {
      const ResourceTypeRecord& type = get_type_record (i);
      /* The check for idx < count is here because ResourceRecord is NOT null-safe.
       * Because an offset of 0 there does NOT mean null. */
      if (type.is_sfnt () && idx < type.get_resource_count ())
	return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
    }
    return Null (OpenTypeFontFace);
  }

  bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  typeList.sanitize (c, this,
				     &(this+typeList),
				     data_base));
  }

  private:
  unsigned int get_type_count () const { return (this+typeList).lenM1 + 1; }

  const ResourceTypeRecord& get_type_record (unsigned int i) const
  { return (this+typeList)[i]; }

  protected:
  HBUINT8	reserved0[16];	/* Reserved for copy of resource header */
  HBUINT32	reserved1;	/* Reserved for handle to next resource map */
  HBUINT16	resreved2;	/* Reserved for file reference number */
  HBUINT16	attrs;		/* Resource fork attribute */
  NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
		typeList;	/* Offset from beginning of map to
				 * resource type list */
  Offset16	nameList;	/* Offset from beginning of map to
				 * resource name list */
  public:
  DEFINE_SIZE_STATIC (28);
};

struct ResourceForkHeader
{
  unsigned int get_face_count () const
  { return (this+map).get_face_count (); }

  const OpenTypeFontFace& get_face (unsigned int idx,
				    unsigned int *base_offset = nullptr) const
  {
    const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
    if (base_offset)
      *base_offset = (const char *) &face - (const char *) this;
    return face;
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this) &&
		  data.sanitize (c, this, dataLen) &&
		  map.sanitize (c, this, &(this+data)));
  }

  protected:
  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
		data;		/* Offset from beginning of resource fork
				 * to resource data */
  LNNOffsetTo<ResourceMap >
		map;		/* Offset from beginning of resource fork
				 * to resource map */
  HBUINT32	dataLen;	/* Length of resource data */
  HBUINT32	mapLen;		/* Length of resource map */
  public:
  DEFINE_SIZE_STATIC (16);
};

/*
 * OpenType Font File
 */

struct OpenTypeFontFile
{
  enum {
    CFFTag		= HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
    TrueTypeTag		= HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
    TTCTag		= HB_TAG ('t','t','c','f'), /* TrueType Collection */
    DFontTag		= HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
    TrueTag		= HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
    Typ1Tag		= HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
  };

  hb_tag_t get_tag () const { return u.tag; }

  unsigned int get_face_count () const
  {
    switch (u.tag) {
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return 1;
    case TTCTag:	return u.ttcHeader.get_face_count ();
    case DFontTag:	return u.rfHeader.get_face_count ();
    default:		return 0;
    }
  }
  const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
  {
    if (base_offset)
      *base_offset = 0;
    switch (u.tag) {
    /* Note: for non-collection SFNT data we ignore index.  This is because
     * Apple dfont container is a container of SFNT's.  So each SFNT is a
     * non-TTC, but the index is more than zero. */
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return u.fontFace;
    case TTCTag:	return u.ttcHeader.get_face (i);
    case DFontTag:	return u.rfHeader.get_face (i, base_offset);
    default:		return Null (OpenTypeFontFace);
    }
  }

  template <typename item_t>
  bool serialize_single (hb_serialize_context_t *c,
			 hb_tag_t sfnt_tag,
			 hb_array_t<item_t> items)
  {
    TRACE_SERIALIZE (this);
    assert (sfnt_tag != TTCTag);
    if (unlikely (!c->extend_min (*this))) return_trace (false);
    return_trace (u.fontFace.serialize (c, sfnt_tag, items));
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
    switch (u.tag) {
    case CFFTag:	/* All the non-collection tags */
    case TrueTag:
    case Typ1Tag:
    case TrueTypeTag:	return_trace (u.fontFace.sanitize (c));
    case TTCTag:	return_trace (u.ttcHeader.sanitize (c));
    case DFontTag:	return_trace (u.rfHeader.sanitize (c));
    default:		return_trace (true);
    }
  }

  protected:
  union {
  Tag			tag;		/* 4-byte identifier. */
  OpenTypeFontFace	fontFace;
  TTCHeader		ttcHeader;
  ResourceForkHeader	rfHeader;
  } u;
  public:
  DEFINE_SIZE_UNION (4, tag);
};

} /* namespace OT */

#endif /* HB_OPEN_FILE_HH */


text:
/*
 * Copyright © 2009  Red Hat, 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
 */

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

#ifndef HB_FACE_H
#define HB_FACE_H

#include "hb-common.h"
#include "hb-blob.h"
#include "hb-set.h"

HB_BEGIN_DECLS

HB_EXTERN unsigned int
hb_face_count (hb_blob_t *blob);

/*
 * hb_face_t
 */

typedef struct hb_face_t hb_face_t;

HB_EXTERN hb_face_t *
hb_face_create (hb_blob_t    *blob,
		unsigned int  index);

typedef hb_blob_t * (*hb_reference_table_func_t)  (hb_face_t *face, hb_tag_t tag, void *user_data);

/* calls destroy() when not needing user_data anymore */
HB_EXTERN hb_face_t *
hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
			   void                      *user_data,
			   hb_destroy_func_t          destroy);

HB_EXTERN hb_face_t *
hb_face_get_empty (void);

HB_EXTERN hb_face_t *
hb_face_reference (hb_face_t *face);

HB_EXTERN void
hb_face_destroy (hb_face_t *face);

HB_EXTERN hb_bool_t
hb_face_set_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key,
		       void *              data,
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace);

HB_EXTERN void *
hb_face_get_user_data (const hb_face_t    *face,
		       hb_user_data_key_t *key);

HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);

HB_EXTERN hb_bool_t
hb_face_is_immutable (const hb_face_t *face);

HB_EXTERN hb_blob_t *
hb_face_reference_table (const hb_face_t *face,
			 hb_tag_t tag);

HB_EXTERN hb_blob_t *
hb_face_reference_blob (hb_face_t *face);

HB_EXTERN void
hb_face_set_index (hb_face_t    *face,
		   unsigned int  index);

HB_EXTERN unsigned int
hb_face_get_index (const hb_face_t *face);

HB_EXTERN void
hb_face_set_upem (hb_face_t    *face,
		  unsigned int  upem);

HB_EXTERN unsigned int
hb_face_get_upem (const hb_face_t *face);

HB_EXTERN void
hb_face_set_glyph_count (hb_face_t    *face,
			 unsigned int  glyph_count);

HB_EXTERN unsigned int
hb_face_get_glyph_count (const hb_face_t *face);

HB_EXTERN unsigned int
hb_face_get_table_tags (const hb_face_t *face,
			unsigned int  start_offset,
			unsigned int *table_count, /* IN/OUT */
			hb_tag_t     *table_tags /* OUT */);

/*
 * Character set.
 */

HB_EXTERN void
hb_face_collect_unicodes (hb_face_t *face,
			  hb_set_t  *out);

HB_EXTERN void
hb_face_collect_variation_selectors (hb_face_t *face,
				     hb_set_t  *out);

HB_EXTERN void
hb_face_collect_variation_unicodes (hb_face_t *face,
				    hb_codepoint_t variation_selector,
				    hb_set_t  *out);

/*
 * Builder face.
 */

HB_EXTERN hb_face_t *
hb_face_builder_create (void);

HB_EXTERN hb_bool_t
hb_face_builder_add_table (hb_face_t *face,
			   hb_tag_t   tag,
			   hb_blob_t *blob);

HB_END_DECLS

#endif /* HB_FACE_H */