Blame src/hb-ot-cmap-table.hh

Packit Service 5bcba8
/*
Packit Service 5bcba8
 * Copyright © 2014  Google, Inc.
Packit Service 5bcba8
 *
Packit Service 5bcba8
 *  This is part of HarfBuzz, a text shaping library.
Packit Service 5bcba8
 *
Packit Service 5bcba8
 * Permission is hereby granted, without written agreement and without
Packit Service 5bcba8
 * license or royalty fees, to use, copy, modify, and distribute this
Packit Service 5bcba8
 * software and its documentation for any purpose, provided that the
Packit Service 5bcba8
 * above copyright notice and the following two paragraphs appear in
Packit Service 5bcba8
 * all copies of this software.
Packit Service 5bcba8
 *
Packit Service 5bcba8
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
Packit Service 5bcba8
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
Packit Service 5bcba8
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
Packit Service 5bcba8
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
Packit Service 5bcba8
 * DAMAGE.
Packit Service 5bcba8
 *
Packit Service 5bcba8
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
Packit Service 5bcba8
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
Packit Service 5bcba8
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
Packit Service 5bcba8
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
Packit Service 5bcba8
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Packit Service 5bcba8
 *
Packit Service 5bcba8
 * Google Author(s): Behdad Esfahbod
Packit Service 5bcba8
 */
Packit Service 5bcba8
Packit Service 5bcba8
#ifndef HB_OT_CMAP_TABLE_HH
Packit Service 5bcba8
#define HB_OT_CMAP_TABLE_HH
Packit Service 5bcba8
Packit Service 5bcba8
#include "hb-open-type-private.hh"
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
namespace OT {
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
/*
Packit Service 5bcba8
 * cmap -- Character To Glyph Index Mapping Table
Packit Service 5bcba8
 */
Packit Service 5bcba8
Packit Service 5bcba8
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat0
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
Packit Service 5bcba8
    if (!gid)
Packit Service 5bcba8
      return false;
Packit Service 5bcba8
    *glyph = gid;
Packit Service 5bcba8
    return true;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  protected:
Packit Service 5bcba8
  USHORT	format;		/* Format number is set to 0. */
Packit Service 5bcba8
  USHORT	lengthZ;	/* Byte length of this subtable. */
Packit Service 5bcba8
  USHORT	languageZ;	/* Ignore. */
Packit Service 5bcba8
  BYTE		glyphIdArray[256];/* An array that maps character
Packit Service 5bcba8
				 * code to glyph index values. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (6 + 256);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat4
Packit Service 5bcba8
{
Packit Service 5bcba8
  struct accelerator_t
Packit Service 5bcba8
  {
Packit Service 5bcba8
    inline void init (const CmapSubtableFormat4 *subtable)
Packit Service 5bcba8
    {
Packit Service 5bcba8
      segCount = subtable->segCountX2 / 2;
Packit Service 5bcba8
      endCount = subtable->values;
Packit Service 5bcba8
      startCount = endCount + segCount + 1;
Packit Service 5bcba8
      idDelta = startCount + segCount;
Packit Service 5bcba8
      idRangeOffset = idDelta + segCount;
Packit Service 5bcba8
      glyphIdArray = idRangeOffset + segCount;
Packit Service 5bcba8
      glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
Packit Service 5bcba8
    }
Packit Service 5bcba8
Packit Service 5bcba8
    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
Packit Service 5bcba8
    {
Packit Service 5bcba8
      const accelerator_t *thiz = (const accelerator_t *) obj;
Packit Service 5bcba8
Packit Service 5bcba8
      /* Custom two-array bsearch. */
Packit Service 5bcba8
      int min = 0, max = (int) thiz->segCount - 1;
Packit Service 5bcba8
      const USHORT *startCount = thiz->startCount;
Packit Service 5bcba8
      const USHORT *endCount = thiz->endCount;
Packit Service 5bcba8
      unsigned int i;
Packit Service 5bcba8
      while (min <= max)
Packit Service 5bcba8
      {
Packit Service 5bcba8
	int mid = (min + max) / 2;
Packit Service 5bcba8
	if (codepoint < startCount[mid])
Packit Service 5bcba8
	  max = mid - 1;
Packit Service 5bcba8
	else if (codepoint > endCount[mid])
Packit Service 5bcba8
	  min = mid + 1;
Packit Service 5bcba8
	else
Packit Service 5bcba8
	{
Packit Service 5bcba8
	  i = mid;
Packit Service 5bcba8
	  goto found;
Packit Service 5bcba8
	}
Packit Service 5bcba8
      }
Packit Service 5bcba8
      return false;
Packit Service 5bcba8
Packit Service 5bcba8
    found:
Packit Service 5bcba8
      hb_codepoint_t gid;
Packit Service 5bcba8
      unsigned int rangeOffset = thiz->idRangeOffset[i];
Packit Service 5bcba8
      if (rangeOffset == 0)
Packit Service 5bcba8
	gid = codepoint + thiz->idDelta[i];
Packit Service 5bcba8
      else
Packit Service 5bcba8
      {
Packit Service 5bcba8
	/* Somebody has been smoking... */
Packit Service 5bcba8
	unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
Packit Service 5bcba8
	if (unlikely (index >= thiz->glyphIdArrayLength))
Packit Service 5bcba8
	  return false;
Packit Service 5bcba8
	gid = thiz->glyphIdArray[index];
Packit Service 5bcba8
	if (unlikely (!gid))
Packit Service 5bcba8
	  return false;
Packit Service 5bcba8
	gid += thiz->idDelta[i];
Packit Service 5bcba8
      }
Packit Service 5bcba8
Packit Service 5bcba8
      *glyph = gid & 0xFFFFu;
Packit Service 5bcba8
      return true;
Packit Service 5bcba8
    }
Packit Service 5bcba8
Packit Service 5bcba8
    const USHORT *endCount;
Packit Service 5bcba8
    const USHORT *startCount;
Packit Service 5bcba8
    const USHORT *idDelta;
Packit Service 5bcba8
    const USHORT *idRangeOffset;
Packit Service 5bcba8
    const USHORT *glyphIdArray;
Packit Service 5bcba8
    unsigned int segCount;
Packit Service 5bcba8
    unsigned int glyphIdArrayLength;
Packit Service 5bcba8
  };
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    accelerator_t accel;
Packit Service 5bcba8
    accel.init (this);
Packit Service 5bcba8
    return accel.get_glyph_func (&accel, codepoint, glyph);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    if (unlikely (!c->check_struct (this)))
Packit Service 5bcba8
      return_trace (false);
Packit Service 5bcba8
Packit Service 5bcba8
    if (unlikely (!c->check_range (this, length)))
Packit Service 5bcba8
    {
Packit Service 5bcba8
      /* Some broken fonts have too long of a "length" value.
Packit Service 5bcba8
       * If that is the case, just change the value to truncate
Packit Service 5bcba8
       * the subtable at the end of the blob. */
Packit Service 5bcba8
      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
Packit Service 5bcba8
					    (uintptr_t) (c->end -
Packit Service 5bcba8
							 (char *) this));
Packit Service 5bcba8
      if (!c->try_set (&length, new_length))
Packit Service 5bcba8
	return_trace (false);
Packit Service 5bcba8
    }
Packit Service 5bcba8
Packit Service 5bcba8
    return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  protected:
Packit Service 5bcba8
  USHORT	format;		/* Format number is set to 4. */
Packit Service 5bcba8
  USHORT	length;		/* This is the length in bytes of the
Packit Service 5bcba8
				 * subtable. */
Packit Service 5bcba8
  USHORT	languageZ;	/* Ignore. */
Packit Service 5bcba8
  USHORT	segCountX2;	/* 2 x segCount. */
Packit Service 5bcba8
  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
Packit Service 5bcba8
  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
Packit Service 5bcba8
  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
Packit Service 5bcba8
Packit Service 5bcba8
  USHORT	values[VAR];
Packit Service 5bcba8
#if 0
Packit Service 5bcba8
  USHORT	endCount[segCount];	/* End characterCode for each segment,
Packit Service 5bcba8
					 * last=0xFFFFu. */
Packit Service 5bcba8
  USHORT	reservedPad;		/* Set to 0. */
Packit Service 5bcba8
  USHORT	startCount[segCount];	/* Start character code for each segment. */
Packit Service 5bcba8
  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
Packit Service 5bcba8
  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
Packit Service 5bcba8
  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
Packit Service 5bcba8
#endif
Packit Service 5bcba8
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_ARRAY (14, values);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableLongGroup
Packit Service 5bcba8
{
Packit Service 5bcba8
  friend struct CmapSubtableFormat12;
Packit Service 5bcba8
  friend struct CmapSubtableFormat13;
Packit Service 5bcba8
Packit Service 5bcba8
  int cmp (hb_codepoint_t codepoint) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    if (codepoint < startCharCode) return -1;
Packit Service 5bcba8
    if (codepoint > endCharCode)   return +1;
Packit Service 5bcba8
    return 0;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  private:
Packit Service 5bcba8
  ULONG		startCharCode;	/* First character code in this group. */
Packit Service 5bcba8
  ULONG		endCharCode;	/* Last character code in this group. */
Packit Service 5bcba8
  ULONG		glyphID;	/* Glyph index; interpretation depends on
Packit Service 5bcba8
				 * subtable format. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (12);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
template <typename UINT>
Packit Service 5bcba8
struct CmapSubtableTrimmed
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    /* Rely on our implicit array bound-checking. */
Packit Service 5bcba8
    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
Packit Service 5bcba8
    if (!gid)
Packit Service 5bcba8
      return false;
Packit Service 5bcba8
    *glyph = gid;
Packit Service 5bcba8
    return true;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  protected:
Packit Service 5bcba8
  UINT		formatReserved;	/* Subtable format and (maybe) padding. */
Packit Service 5bcba8
  UINT		lengthZ;	/* Byte length of this subtable. */
Packit Service 5bcba8
  UINT		languageZ;	/* Ignore. */
Packit Service 5bcba8
  UINT		startCharCode;	/* First character code covered. */
Packit Service 5bcba8
  ArrayOf<GlyphID, UINT>
Packit Service 5bcba8
		glyphIdArray;	/* Array of glyph index values for character
Packit Service 5bcba8
				 * codes in the range. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
Packit Service 5bcba8
struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
Packit Service 5bcba8
Packit Service 5bcba8
template <typename T>
Packit Service 5bcba8
struct CmapSubtableLongSegmented
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    int i = groups.bsearch (codepoint);
Packit Service 5bcba8
    if (i == -1)
Packit Service 5bcba8
      return false;
Packit Service 5bcba8
    *glyph = T::group_get_glyph (groups[i], codepoint);
Packit Service 5bcba8
    return true;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) && groups.sanitize (c));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  protected:
Packit Service 5bcba8
  USHORT	format;		/* Subtable format; set to 12. */
Packit Service 5bcba8
  USHORT	reservedZ;	/* Reserved; set to 0. */
Packit Service 5bcba8
  ULONG		lengthZ;	/* Byte length of this subtable. */
Packit Service 5bcba8
  ULONG		languageZ;	/* Ignore. */
Packit Service 5bcba8
  SortedArrayOf<CmapSubtableLongGroup, ULONG>
Packit Service 5bcba8
		groups;		/* Groupings. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_ARRAY (16, groups);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
Packit Service 5bcba8
{
Packit Service 5bcba8
  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
Packit Service 5bcba8
						hb_codepoint_t u)
Packit Service 5bcba8
  { return group.glyphID + (u - group.startCharCode); }
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
Packit Service 5bcba8
{
Packit Service 5bcba8
  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
Packit Service 5bcba8
						hb_codepoint_t u HB_UNUSED)
Packit Service 5bcba8
  { return group.glyphID; }
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
typedef enum
Packit Service 5bcba8
{
Packit Service 5bcba8
  GLYPH_VARIANT_NOT_FOUND = 0,
Packit Service 5bcba8
  GLYPH_VARIANT_FOUND = 1,
Packit Service 5bcba8
  GLYPH_VARIANT_USE_DEFAULT = 2
Packit Service 5bcba8
} glyph_variant_t;
Packit Service 5bcba8
Packit Service 5bcba8
struct UnicodeValueRange
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline int cmp (const hb_codepoint_t &codepoint) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    if (codepoint < startUnicodeValue) return -1;
Packit Service 5bcba8
    if (codepoint > startUnicodeValue + additionalCount) return +1;
Packit Service 5bcba8
    return 0;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  UINT24	startUnicodeValue;	/* First value in this range. */
Packit Service 5bcba8
  BYTE		additionalCount;	/* Number of additional values in this
Packit Service 5bcba8
					 * range. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (4);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
Packit Service 5bcba8
Packit Service 5bcba8
struct UVSMapping
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline int cmp (const hb_codepoint_t &codepoint) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    return unicodeValue.cmp (codepoint);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
Packit Service 5bcba8
  GlyphID	glyphID;	/* Glyph ID of the UVS */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (5);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
Packit Service 5bcba8
Packit Service 5bcba8
struct VariationSelectorRecord
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
Packit Service 5bcba8
				    hb_codepoint_t *glyph,
Packit Service 5bcba8
				    const void *base) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    int i;
Packit Service 5bcba8
    const DefaultUVS &defaults = base+defaultUVS;
Packit Service 5bcba8
    i = defaults.bsearch (codepoint);
Packit Service 5bcba8
    if (i != -1)
Packit Service 5bcba8
      return GLYPH_VARIANT_USE_DEFAULT;
Packit Service 5bcba8
    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
Packit Service 5bcba8
    i = nonDefaults.bsearch (codepoint);
Packit Service 5bcba8
    if (i != -1)
Packit Service 5bcba8
    {
Packit Service 5bcba8
      *glyph = nonDefaults[i].glyphID;
Packit Service 5bcba8
       return GLYPH_VARIANT_FOUND;
Packit Service 5bcba8
    }
Packit Service 5bcba8
    return GLYPH_VARIANT_NOT_FOUND;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline int cmp (const hb_codepoint_t &variation_selector) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    return varSelector.cmp (variation_selector);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) &&
Packit Service 5bcba8
		  defaultUVS.sanitize (c, base) &&
Packit Service 5bcba8
		  nonDefaultUVS.sanitize (c, base));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  UINT24	varSelector;	/* Variation selector. */
Packit Service 5bcba8
  LOffsetTo<DefaultUVS>
Packit Service 5bcba8
		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
Packit Service 5bcba8
  LOffsetTo<NonDefaultUVS>
Packit Service 5bcba8
		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (11);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtableFormat14
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
Packit Service 5bcba8
					    hb_codepoint_t variation_selector,
Packit Service 5bcba8
					    hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) &&
Packit Service 5bcba8
		  record.sanitize (c, this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  protected:
Packit Service 5bcba8
  USHORT	format;		/* Format number is set to 14. */
Packit Service 5bcba8
  ULONG		lengthZ;	/* Byte length of this subtable. */
Packit Service 5bcba8
  SortedArrayOf<VariationSelectorRecord, ULONG>
Packit Service 5bcba8
		record;		/* Variation selector records; sorted
Packit Service 5bcba8
				 * in increasing order of `varSelector'. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_ARRAY (10, record);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct CmapSubtable
Packit Service 5bcba8
{
Packit Service 5bcba8
  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool get_glyph (hb_codepoint_t codepoint,
Packit Service 5bcba8
			 hb_codepoint_t *glyph) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    switch (u.format) {
Packit Service 5bcba8
    case  0: return u.format0 .get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case  4: return u.format4 .get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case  6: return u.format6 .get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case 10: return u.format10.get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case 12: return u.format12.get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case 13: return u.format13.get_glyph(codepoint, glyph);
Packit Service 5bcba8
    case 14:
Packit Service 5bcba8
    default: return false;
Packit Service 5bcba8
    }
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    if (!u.format.sanitize (c)) return_trace (false);
Packit Service 5bcba8
    switch (u.format) {
Packit Service 5bcba8
    case  0: return_trace (u.format0 .sanitize (c));
Packit Service 5bcba8
    case  4: return_trace (u.format4 .sanitize (c));
Packit Service 5bcba8
    case  6: return_trace (u.format6 .sanitize (c));
Packit Service 5bcba8
    case 10: return_trace (u.format10.sanitize (c));
Packit Service 5bcba8
    case 12: return_trace (u.format12.sanitize (c));
Packit Service 5bcba8
    case 13: return_trace (u.format13.sanitize (c));
Packit Service 5bcba8
    case 14: return_trace (u.format14.sanitize (c));
Packit Service 5bcba8
    default:return_trace (true);
Packit Service 5bcba8
    }
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  union {
Packit Service 5bcba8
  USHORT		format;		/* Format identifier */
Packit Service 5bcba8
  CmapSubtableFormat0	format0;
Packit Service 5bcba8
  CmapSubtableFormat4	format4;
Packit Service 5bcba8
  CmapSubtableFormat6	format6;
Packit Service 5bcba8
  CmapSubtableFormat10	format10;
Packit Service 5bcba8
  CmapSubtableFormat12	format12;
Packit Service 5bcba8
  CmapSubtableFormat13	format13;
Packit Service 5bcba8
  CmapSubtableFormat14	format14;
Packit Service 5bcba8
  } u;
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_UNION (2, format);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
struct EncodingRecord
Packit Service 5bcba8
{
Packit Service 5bcba8
  inline int cmp (const EncodingRecord &other) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    int ret;
Packit Service 5bcba8
    ret = platformID.cmp (other.platformID);
Packit Service 5bcba8
    if (ret) return ret;
Packit Service 5bcba8
    ret = encodingID.cmp (other.encodingID);
Packit Service 5bcba8
    if (ret) return ret;
Packit Service 5bcba8
    return 0;
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) &&
Packit Service 5bcba8
		  subtable.sanitize (c, base));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  USHORT	platformID;	/* Platform ID. */
Packit Service 5bcba8
  USHORT	encodingID;	/* Platform-specific encoding ID. */
Packit Service 5bcba8
  LOffsetTo<CmapSubtable>
Packit Service 5bcba8
		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_STATIC (8);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
struct cmap
Packit Service 5bcba8
{
Packit Service 5bcba8
  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
Packit Service 5bcba8
Packit Service 5bcba8
  inline const CmapSubtable *find_subtable (unsigned int platform_id,
Packit Service 5bcba8
					    unsigned int encoding_id) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    EncodingRecord key;
Packit Service 5bcba8
    key.platformID.set (platform_id);
Packit Service 5bcba8
    key.encodingID.set (encoding_id);
Packit Service 5bcba8
Packit Service 5bcba8
    /* Note: We can use bsearch, but since it has no performance
Packit Service 5bcba8
     * implications, we use lsearch and as such accept fonts with
Packit Service 5bcba8
     * unsorted subtable list. */
Packit Service 5bcba8
    int result = encodingRecord./*bsearch*/lsearch (key);
Packit Service 5bcba8
    if (result == -1 || !encodingRecord[result].subtable)
Packit Service 5bcba8
      return NULL;
Packit Service 5bcba8
Packit Service 5bcba8
    return &(this+encodingRecord[result].subtable);
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  inline bool sanitize (hb_sanitize_context_t *c) const
Packit Service 5bcba8
  {
Packit Service 5bcba8
    TRACE_SANITIZE (this);
Packit Service 5bcba8
    return_trace (c->check_struct (this) &&
Packit Service 5bcba8
		  likely (version == 0) &&
Packit Service 5bcba8
		  encodingRecord.sanitize (c, this));
Packit Service 5bcba8
  }
Packit Service 5bcba8
Packit Service 5bcba8
  USHORT		version;	/* Table version number (0). */
Packit Service 5bcba8
  SortedArrayOf<EncodingRecord>
Packit Service 5bcba8
			encodingRecord;	/* Encoding tables. */
Packit Service 5bcba8
  public:
Packit Service 5bcba8
  DEFINE_SIZE_ARRAY (4, encodingRecord);
Packit Service 5bcba8
};
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
} /* namespace OT */
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
#endif /* HB_OT_CMAP_TABLE_HH */