141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod/*
241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * Copyright © 2014  Google, Inc.
341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *
441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *
641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * Permission is hereby granted, without written agreement and without
741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * software and its documentation for any purpose, provided that the
941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
1041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * all copies of this software.
1141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *
1241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * DAMAGE.
1741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *
1841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
1941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod *
2441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * Google Author(s): Behdad Esfahbod
2541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod */
2641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
2741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#ifndef HB_OT_CMAP_TABLE_HH
2841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#define HB_OT_CMAP_TABLE_HH
2941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
3041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#include "hb-open-type-private.hh"
3141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
3241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
3341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodnamespace OT {
3441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
3541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
3641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod/*
3741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod * cmap -- Character To Glyph Index Mapping Table
3841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod */
3941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
4141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
43b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbodstruct CmapSubtableFormat0
44b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod{
45b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
46b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  {
47b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
48b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    if (!gid)
49b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod      return false;
50b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    *glyph = gid;
51b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    return true;
52b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  }
53b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod
54de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
55de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
56b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    TRACE_SANITIZE (this);
57b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
58b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  }
59b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod
60b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  protected:
61b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  USHORT	format;		/* Format number is set to 0. */
627d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	lengthZ;	/* Byte length of this subtable. */
637d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	languageZ;	/* Ignore. */
64b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  BYTE		glyphIdArray[256];/* An array that maps character
65b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod				 * code to glyph index values. */
66b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  public:
67b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  DEFINE_SIZE_STATIC (6 + 256);
68b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod};
69b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod
7041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct CmapSubtableFormat4
7141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
7223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod  struct accelerator_t
7341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
7423335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    inline void init (const CmapSubtableFormat4 *subtable)
7523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    {
7623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      segCount = subtable->segCountX2 / 2;
7723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      endCount = subtable->values;
7823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      startCount = endCount + segCount + 1;
7923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      idDelta = startCount + segCount;
8023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      idRangeOffset = idDelta + segCount;
8123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      glyphIdArray = idRangeOffset + segCount;
8223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
8323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    }
84c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
8523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
86c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    {
8723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      const accelerator_t *thiz = (const accelerator_t *) obj;
8823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod
8923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      /* Custom two-array bsearch. */
9023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      int min = 0, max = (int) thiz->segCount - 1;
9123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      const USHORT *startCount = thiz->startCount;
9223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      const USHORT *endCount = thiz->endCount;
9323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      unsigned int i;
9423335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      while (min <= max)
9523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      {
9623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	int mid = (min + max) / 2;
9723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	if (codepoint < startCount[mid])
9823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  max = mid - 1;
9923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	else if (codepoint > endCount[mid])
10023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  min = mid + 1;
10123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	else
10223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	{
10323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  i = mid;
10423335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  goto found;
10523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	}
10623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      }
10723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      return false;
10823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod
10923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    found:
11023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      hb_codepoint_t gid;
11123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      unsigned int rangeOffset = thiz->idRangeOffset[i];
11223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      if (rangeOffset == 0)
11323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	gid = codepoint + thiz->idDelta[i];
114c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      else
115c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      {
11623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	/* Somebody has been smoking... */
11723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
11823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	if (unlikely (index >= thiz->glyphIdArrayLength))
11923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  return false;
12023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	gid = thiz->glyphIdArray[index];
12123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	if (unlikely (!gid))
12223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	  return false;
12323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod	gid += thiz->idDelta[i];
124c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      }
12523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod
12623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      *glyph = gid & 0xFFFFu;
12723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod      return true;
128c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    }
129c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
13023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    const USHORT *endCount;
13123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    const USHORT *startCount;
13223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    const USHORT *idDelta;
13323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    const USHORT *idRangeOffset;
13423335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    const USHORT *glyphIdArray;
13523335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    unsigned int segCount;
13623335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    unsigned int glyphIdArrayLength;
13723335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod  };
13823335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod
13923335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
14023335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod  {
14123335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    accelerator_t accel;
14223335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    accel.init (this);
14323335deaad9d4d9824ff41343264514d3f9f7e37Behdad Esfahbod    return accel.get_glyph_func (&accel, codepoint, glyph);
14441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
14541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
146de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
147257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod  {
14841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
149257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_struct (this)))
150b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod      return_trace (false);
151257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
152257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_range (this, length)))
153257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    {
154257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      /* Some broken fonts have too long of a "length" value.
155257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * If that is the case, just change the value to truncate
156257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * the subtable at the end of the blob. */
157257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
158257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod					    (uintptr_t) (c->end -
159257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod							 (char *) this));
160257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      if (!c->try_set (&length, new_length))
161b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod	return_trace (false);
162257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    }
163257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
164b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
16541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
16641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
16741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  protected:
16841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	format;		/* Format number is set to 4. */
16941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	length;		/* This is the length in bytes of the
17041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod				 * subtable. */
1717d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	languageZ;	/* Ignore. */
17241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	segCountX2;	/* 2 x segCount. */
1737d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
1747d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
1757d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
17641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
17741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	values[VAR];
17841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#if 0
17941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	endCount[segCount];	/* End characterCode for each segment,
1807627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod					 * last=0xFFFFu. */
18141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	reservedPad;		/* Set to 0. */
18241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	startCount[segCount];	/* Start character code for each segment. */
18341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
18441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
18541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
18641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif
18741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
18841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
18941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (14, values);
19041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
19141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
192d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbodstruct CmapSubtableLongGroup
1930d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
1940d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  friend struct CmapSubtableFormat12;
195d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  friend struct CmapSubtableFormat13;
1960d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1970d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  int cmp (hb_codepoint_t codepoint) const
1980d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
1990d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint < startCharCode) return -1;
2000d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint > endCharCode)   return +1;
2010d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return 0;
2020d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2030d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
204de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
205de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
2060d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
207b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
2080d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2090d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
2100d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  private:
2110d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		startCharCode;	/* First character code in this group. */
2120d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		endCharCode;	/* Last character code in this group. */
213d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  ULONG		glyphID;	/* Glyph index; interpretation depends on
214d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod				 * subtable format. */
2150d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  public:
2160d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  DEFINE_SIZE_STATIC (12);
2170d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
2180d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
21994759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodtemplate <typename UINT>
22094759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableTrimmed
22191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod{
22291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
22391bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  {
22491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    /* Rely on our implicit array bound-checking. */
22591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
22691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    if (!gid)
22791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod      return false;
22891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    *glyph = gid;
22991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    return true;
23091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
23191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
232de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
233de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
23491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    TRACE_SANITIZE (this);
235b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
23691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
23791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
23891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  protected:
23994759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		formatReserved;	/* Subtable format and (maybe) padding. */
2407d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		lengthZ;	/* Byte length of this subtable. */
2417d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		languageZ;	/* Ignore. */
24294759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		startCharCode;	/* First character code covered. */
2439da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod  ArrayOf<GlyphID, UINT>
24491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod		glyphIdArray;	/* Array of glyph index values for character
24591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod				 * codes in the range. */
24691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  public:
24794759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
24891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod};
24991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
25094759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
25194759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
25291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
253ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodtemplate <typename T>
254ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableLongSegmented
2550d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
2560d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
2570d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
258df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int i = groups.bsearch (codepoint);
2590d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (i == -1)
2600d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod      return false;
261ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod    *glyph = T::group_get_glyph (groups[i], codepoint);
2620d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return true;
2630d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2640d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
265de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
266de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
2670d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
268b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) && groups.sanitize (c));
2690d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2700d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
2710d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  protected:
2720d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  USHORT	format;		/* Subtable format; set to 12. */
2737d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	reservedZ;	/* Reserved; set to 0. */
2747d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
2757d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		languageZ;	/* Ignore. */
27641ea59495032e712fa6f801350ee00d5f00b5724Behdad Esfahbod  SortedArrayOf<CmapSubtableLongGroup, ULONG>
277d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod		groups;		/* Groupings. */
278d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  public:
279d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  DEFINE_SIZE_ARRAY (16, groups);
280d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod};
281d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
282ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
283d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod{
284ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
285ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u)
286ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID + (u - group.startCharCode); }
287ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod};
288d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
289ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
290ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod{
291ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
292ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u HB_UNUSED)
293ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID; }
2940d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
2950d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
296a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef enum
297a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
298a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_NOT_FOUND = 0,
299a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_FOUND = 1,
300a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_USE_DEFAULT = 2
301a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod} glyph_variant_t;
302a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
303a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UnicodeValueRange
304a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
305a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
306a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
307a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint < startUnicodeValue) return -1;
308a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint > startUnicodeValue + additionalCount) return +1;
309a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return 0;
310a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
311a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
312de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
313de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
314a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
315b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
316a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
317a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
318a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	startUnicodeValue;	/* First value in this range. */
319a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  BYTE		additionalCount;	/* Number of additional values in this
320a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					 * range. */
321a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
322a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (4);
323a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
324a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
325a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
326a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
327a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UVSMapping
328a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
329a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
330a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
331a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return unicodeValue.cmp (codepoint);
332a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
333a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
334de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
335de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
336a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
337b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
338a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
339a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
340a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
341a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GlyphID	glyphID;	/* Glyph ID of the UVS */
342a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
343a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (5);
344a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
345a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
346a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
347a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
348a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct VariationSelectorRecord
349a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
350a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
351a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    hb_codepoint_t *glyph,
352a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    const void *base) const
353a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
354a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    int i;
355a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const DefaultUVS &defaults = base+defaultUVS;
356a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = defaults.bsearch (codepoint);
357a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
358a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      return GLYPH_VARIANT_USE_DEFAULT;
359a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
360a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = nonDefaults.bsearch (codepoint);
361a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
362a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    {
363a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      *glyph = nonDefaults[i].glyphID;
364a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod       return GLYPH_VARIANT_FOUND;
365a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
366a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return GLYPH_VARIANT_NOT_FOUND;
367a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
368a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
369a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &variation_selector) const
370a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
371a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return varSelector.cmp (variation_selector);
372a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
373a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
374de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
375de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
376a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
377b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
378b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  defaultUVS.sanitize (c, base) &&
379b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  nonDefaultUVS.sanitize (c, base));
380a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
381a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
382a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	varSelector;	/* Variation selector. */
3835e156fa5ed33cd1a8ff388833563f15930bb12f9Behdad Esfahbod  LOffsetTo<DefaultUVS>
384a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
3855e156fa5ed33cd1a8ff388833563f15930bb12f9Behdad Esfahbod  LOffsetTo<NonDefaultUVS>
386a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
387a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
388a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (11);
389a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
390a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
391a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct CmapSubtableFormat14
392a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
393a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
394a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t variation_selector,
395a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t *glyph) const
396a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
397a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
398a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
399a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
400de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
401de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
402a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
403b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
404b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  record.sanitize (c, this));
405a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
406a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
407a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  protected:
4085473ebfb84c7b6059ac16e04676b363acc51aa00Behdad Esfahbod  USHORT	format;		/* Format number is set to 14. */
4097d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
410a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  SortedArrayOf<VariationSelectorRecord, ULONG>
411a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		record;		/* Variation selector records; sorted
412a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				 * in increasing order of `varSelector'. */
413a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
414a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_ARRAY (10, record);
415a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
416a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
41741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct CmapSubtable
41841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
419c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
420c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod
421a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint,
422a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 hb_codepoint_t *glyph) const
42341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
42441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
425b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    case  0: return u.format0 .get_glyph(codepoint, glyph);
4260d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case  4: return u.format4 .get_glyph(codepoint, glyph);
42791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case  6: return u.format6 .get_glyph(codepoint, glyph);
42891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case 10: return u.format10.get_glyph(codepoint, glyph);
4290d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case 12: return u.format12.get_glyph(codepoint, glyph);
430d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod    case 13: return u.format13.get_glyph(codepoint, glyph);
431a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    case 14:
432a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    default: return false;
433a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
434a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
435a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
436de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
437de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
43841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
439b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    if (!u.format.sanitize (c)) return_trace (false);
44041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
441b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  0: return_trace (u.format0 .sanitize (c));
442b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  4: return_trace (u.format4 .sanitize (c));
443b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  6: return_trace (u.format6 .sanitize (c));
444b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 10: return_trace (u.format10.sanitize (c));
445b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 12: return_trace (u.format12.sanitize (c));
446b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 13: return_trace (u.format13.sanitize (c));
447b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 14: return_trace (u.format14.sanitize (c));
448b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    default:return_trace (true);
44941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    }
45041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
45141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4525473ebfb84c7b6059ac16e04676b363acc51aa00Behdad Esfahbod  public:
45341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  union {
45441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT		format;		/* Format identifier */
455b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  CmapSubtableFormat0	format0;
45641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  CmapSubtableFormat4	format4;
45791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat6	format6;
45891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat10	format10;
4590d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  CmapSubtableFormat12	format12;
460d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  CmapSubtableFormat13	format13;
461a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  CmapSubtableFormat14	format14;
46241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  } u;
46341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
46441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_UNION (2, format);
46541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
46641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
46741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
46841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct EncodingRecord
46941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
470f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  inline int cmp (const EncodingRecord &other) const
47141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
47241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    int ret;
473f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = platformID.cmp (other.platformID);
47441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
475f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = encodingID.cmp (other.encodingID);
47641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
47741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return 0;
47841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
47941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
480de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
481de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
48241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
483b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
484b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  subtable.sanitize (c, base));
48541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
48641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
48741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	platformID;	/* Platform ID. */
48841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	encodingID;	/* Platform-specific encoding ID. */
4895e156fa5ed33cd1a8ff388833563f15930bb12f9Behdad Esfahbod  LOffsetTo<CmapSubtable>
49041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
49141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
49241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_STATIC (8);
49341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
49441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
49541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct cmap
49641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
49741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
49841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4993608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod  inline const CmapSubtable *find_subtable (unsigned int platform_id,
5003608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod					    unsigned int encoding_id) const
50141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
50241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    EncodingRecord key;
50341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.platformID.set (platform_id);
50441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.encodingID.set (encoding_id);
50541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
506df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    /* Note: We can use bsearch, but since it has no performance
507df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * implications, we use lsearch and as such accept fonts with
508df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * unsorted subtable list. */
509df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int result = encodingRecord./*bsearch*/lsearch (key);
510500737e8e16dce5248aff394899bb3761a9c3bbfBehdad Esfahbod    if (result == -1 || !encodingRecord[result].subtable)
5113608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod      return NULL;
5123608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod
5133608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod    return &(this+encodingRecord[result].subtable);
51441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
51541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
516de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
517de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
51841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
519b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
520b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  likely (version == 0) &&
521b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  encodingRecord.sanitize (c, this));
52241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
52341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
524f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  USHORT		version;	/* Table version number (0). */
525df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod  SortedArrayOf<EncodingRecord>
526f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod			encodingRecord;	/* Encoding tables. */
52741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
52841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (4, encodingRecord);
52941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
53041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
53141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
53241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod} /* namespace OT */
53341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
53441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
53541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif /* HB_OT_CMAP_TABLE_HH */
536