hb-ot-cmap-table.hh revision b47159011ca518c3b94d782ed16a91ffe9dd2ab2
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{
7241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
7341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
74c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int segCount;
75c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *endCount;
76c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *startCount;
77c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *idDelta;
78c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *idRangeOffset;
79c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *glyphIdArray;
80c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int glyphIdArrayLength;
81c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
82c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    segCount = this->segCountX2 / 2;
83c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    endCount = this->values;
84c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    startCount = endCount + segCount + 1;
85c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    idDelta = startCount + segCount;
86c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    idRangeOffset = idDelta + segCount;
87c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    glyphIdArray = idRangeOffset + segCount;
88c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
89c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
90df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    /* Custom two-array bsearch. */
91c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    int min = 0, max = (int) segCount - 1;
92c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int i;
93c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    while (min <= max)
94c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    {
95c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      int mid = (min + max) / 2;
96c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (codepoint < startCount[mid])
97c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod        max = mid - 1;
98c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      else if (codepoint > endCount[mid])
99c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod        min = mid + 1;
100c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      else
101c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      {
102c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	i = mid;
103c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	goto found;
104c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      }
105c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    }
10641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return false;
107c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
108c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod  found:
109c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    hb_codepoint_t gid;
110c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int rangeOffset = idRangeOffset[i];
111c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    if (rangeOffset == 0)
112c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid = codepoint + idDelta[i];
113c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    else
114c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    {
115c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      /* Somebody has been smoking... */
116c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
117c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (unlikely (index >= glyphIdArrayLength))
118c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	return false;
119c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid = glyphIdArray[index];
120c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (unlikely (!gid))
121c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	return false;
122c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid += idDelta[i];
123c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    }
124c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
1257627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    *glyph = gid & 0xFFFFu;
126c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    return true;
12741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
12841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
129de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
130257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod  {
13141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
132257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_struct (this)))
133b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod      return_trace (false);
134257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
135257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_range (this, length)))
136257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    {
137257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      /* Some broken fonts have too long of a "length" value.
138257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * If that is the case, just change the value to truncate
139257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * the subtable at the end of the blob. */
140257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
141257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod					    (uintptr_t) (c->end -
142257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod							 (char *) this));
143257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      if (!c->try_set (&length, new_length))
144b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod	return_trace (false);
145257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    }
146257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
147b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
14841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
14941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
15041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  protected:
15141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	format;		/* Format number is set to 4. */
15241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	length;		/* This is the length in bytes of the
15341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod				 * subtable. */
1547d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	languageZ;	/* Ignore. */
15541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	segCountX2;	/* 2 x segCount. */
1567d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
1577d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
1587d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
15941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
16041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	values[VAR];
16141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#if 0
16241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	endCount[segCount];	/* End characterCode for each segment,
1637627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod					 * last=0xFFFFu. */
16441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	reservedPad;		/* Set to 0. */
16541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	startCount[segCount];	/* Start character code for each segment. */
16641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
16741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
16841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
16941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif
17041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
17141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
17241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (14, values);
17341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
17441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
175d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbodstruct CmapSubtableLongGroup
1760d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
1770d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  friend struct CmapSubtableFormat12;
178d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  friend struct CmapSubtableFormat13;
1790d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1800d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  int cmp (hb_codepoint_t codepoint) const
1810d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
1820d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint < startCharCode) return -1;
1830d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint > endCharCode)   return +1;
1840d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return 0;
1850d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
1860d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
187de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
188de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
1890d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
190b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
1910d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
1920d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1930d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  private:
1940d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		startCharCode;	/* First character code in this group. */
1950d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		endCharCode;	/* Last character code in this group. */
196d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  ULONG		glyphID;	/* Glyph index; interpretation depends on
197d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod				 * subtable format. */
1980d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  public:
1990d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  DEFINE_SIZE_STATIC (12);
2000d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
2010d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
20294759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodtemplate <typename UINT>
20394759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableTrimmed
20491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod{
20591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
20691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  {
20791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    /* Rely on our implicit array bound-checking. */
20891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
20991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    if (!gid)
21091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod      return false;
21191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    *glyph = gid;
21291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    return true;
21391bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
21491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
215de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
216de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
21791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    TRACE_SANITIZE (this);
218b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
21991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
22091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
22191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  protected:
22294759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		formatReserved;	/* Subtable format and (maybe) padding. */
2237d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		lengthZ;	/* Byte length of this subtable. */
2247d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		languageZ;	/* Ignore. */
22594759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		startCharCode;	/* First character code covered. */
2269da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod  ArrayOf<GlyphID, UINT>
22791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod		glyphIdArray;	/* Array of glyph index values for character
22891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod				 * codes in the range. */
22991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  public:
23094759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
23191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod};
23291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
23394759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
23494759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
23591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
236ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodtemplate <typename T>
237ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableLongSegmented
2380d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
2390d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
2400d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
241df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int i = groups.bsearch (codepoint);
2420d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (i == -1)
2430d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod      return false;
244ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod    *glyph = T::group_get_glyph (groups[i], codepoint);
2450d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return true;
2460d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2470d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
248de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
249de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
2500d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
251b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) && groups.sanitize (c));
2520d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2530d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
2540d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  protected:
2550d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  USHORT	format;		/* Subtable format; set to 12. */
2567d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	reservedZ;	/* Reserved; set to 0. */
2577d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
2587d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		languageZ;	/* Ignore. */
25941ea59495032e712fa6f801350ee00d5f00b5724Behdad Esfahbod  SortedArrayOf<CmapSubtableLongGroup, ULONG>
260d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod		groups;		/* Groupings. */
261d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  public:
262d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  DEFINE_SIZE_ARRAY (16, groups);
263d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod};
264d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
265ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
266d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod{
267ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
268ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u)
269ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID + (u - group.startCharCode); }
270ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod};
271d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
272ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
273ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod{
274ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
275ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u HB_UNUSED)
276ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID; }
2770d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
2780d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
279a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef enum
280a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
281a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_NOT_FOUND = 0,
282a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_FOUND = 1,
283a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_USE_DEFAULT = 2
284a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod} glyph_variant_t;
285a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
286a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UnicodeValueRange
287a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
288a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
289a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
290a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint < startUnicodeValue) return -1;
291a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint > startUnicodeValue + additionalCount) return +1;
292a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return 0;
293a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
294a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
295de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
296de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
297a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
298b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
299a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
300a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
301a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	startUnicodeValue;	/* First value in this range. */
302a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  BYTE		additionalCount;	/* Number of additional values in this
303a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					 * range. */
304a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
305a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (4);
306a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
307a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
308a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
309a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
310a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UVSMapping
311a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
312a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
313a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
314a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return unicodeValue.cmp (codepoint);
315a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
316a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
317de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
318de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
319a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
320b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this));
321a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
322a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
323a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
324a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GlyphID	glyphID;	/* Glyph ID of the UVS */
325a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
326a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (5);
327a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
328a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
329a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
330a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
331a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct VariationSelectorRecord
332a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
333a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
334a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    hb_codepoint_t *glyph,
335a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    const void *base) const
336a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
337a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    int i;
338a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const DefaultUVS &defaults = base+defaultUVS;
339a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = defaults.bsearch (codepoint);
340a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
341a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      return GLYPH_VARIANT_USE_DEFAULT;
342a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
343a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = nonDefaults.bsearch (codepoint);
344a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
345a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    {
346a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      *glyph = nonDefaults[i].glyphID;
347a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod       return GLYPH_VARIANT_FOUND;
348a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
349a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return GLYPH_VARIANT_NOT_FOUND;
350a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
351a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
352a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &variation_selector) const
353a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
354a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return varSelector.cmp (variation_selector);
355a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
356a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
357de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
358de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
359a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
360b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
361b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  defaultUVS.sanitize (c, base) &&
362b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  nonDefaultUVS.sanitize (c, base));
363a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
364a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
365a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	varSelector;	/* Variation selector. */
366a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  OffsetTo<DefaultUVS, ULONG>
367a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
368a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  OffsetTo<NonDefaultUVS, ULONG>
369a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
370a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
371a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (11);
372a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
373a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
374a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct CmapSubtableFormat14
375a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
376a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
377a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t variation_selector,
378a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t *glyph) const
379a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
380a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
381a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
382a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
383de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
384de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
385a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
386b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
387b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  record.sanitize (c, this));
388a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
389a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
390a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  protected:
391a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  USHORT	format;		/* Format number is set to 0. */
3927d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
393a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  SortedArrayOf<VariationSelectorRecord, ULONG>
394a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		record;		/* Variation selector records; sorted
395a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				 * in increasing order of `varSelector'. */
396a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
397a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_ARRAY (10, record);
398a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
399a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
40041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct CmapSubtable
40141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
402c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
403c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod
404a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint,
405a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 hb_codepoint_t *glyph) const
40641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
40741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
408b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    case  0: return u.format0 .get_glyph(codepoint, glyph);
4090d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case  4: return u.format4 .get_glyph(codepoint, glyph);
41091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case  6: return u.format6 .get_glyph(codepoint, glyph);
41191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case 10: return u.format10.get_glyph(codepoint, glyph);
4120d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case 12: return u.format12.get_glyph(codepoint, glyph);
413d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod    case 13: return u.format13.get_glyph(codepoint, glyph);
414a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    case 14:
415a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    default: return false;
416a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
417a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
418a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
419a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
420a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t variation_selector,
421a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t *glyph) const
422a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
423a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    switch (u.format) {
424a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
425a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    default: return GLYPH_VARIANT_NOT_FOUND;
42641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    }
42741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
42841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
429de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
430de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
43141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
432b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    if (!u.format.sanitize (c)) return_trace (false);
43341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
434b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  0: return_trace (u.format0 .sanitize (c));
435b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  4: return_trace (u.format4 .sanitize (c));
436b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case  6: return_trace (u.format6 .sanitize (c));
437b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 10: return_trace (u.format10.sanitize (c));
438b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 12: return_trace (u.format12.sanitize (c));
439b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 13: return_trace (u.format13.sanitize (c));
440b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    case 14: return_trace (u.format14.sanitize (c));
441b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    default:return_trace (true);
44241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    }
44341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
44441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
44541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  protected:
44641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  union {
44741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT		format;		/* Format identifier */
448b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  CmapSubtableFormat0	format0;
44941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  CmapSubtableFormat4	format4;
45091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat6	format6;
45191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat10	format10;
4520d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  CmapSubtableFormat12	format12;
453d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  CmapSubtableFormat13	format13;
454a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  CmapSubtableFormat14	format14;
45541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  } u;
45641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
45741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_UNION (2, format);
45841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
45941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
46041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
46141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct EncodingRecord
46241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
463f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  inline int cmp (const EncodingRecord &other) const
46441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
46541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    int ret;
466f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = platformID.cmp (other.platformID);
46741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
468f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = encodingID.cmp (other.encodingID);
46941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
47041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return 0;
47141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
47241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
473de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
474de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
47541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
476b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
477b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  subtable.sanitize (c, base));
47841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
47941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
48041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	platformID;	/* Platform ID. */
48141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	encodingID;	/* Platform-specific encoding ID. */
4829da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod  OffsetTo<CmapSubtable, ULONG>
48341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
48441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
48541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_STATIC (8);
48641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
48741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
48841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct cmap
48941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
49041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
49141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4923608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod  inline const CmapSubtable *find_subtable (unsigned int platform_id,
4933608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod					    unsigned int encoding_id) const
49441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
49541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    EncodingRecord key;
49641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.platformID.set (platform_id);
49741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.encodingID.set (encoding_id);
49841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
499df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    /* Note: We can use bsearch, but since it has no performance
500df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * implications, we use lsearch and as such accept fonts with
501df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * unsorted subtable list. */
502df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int result = encodingRecord./*bsearch*/lsearch (key);
503500737e8e16dce5248aff394899bb3761a9c3bbfBehdad Esfahbod    if (result == -1 || !encodingRecord[result].subtable)
5043608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod      return NULL;
5053608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod
5063608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod    return &(this+encodingRecord[result].subtable);
50741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
50841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
509de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) const
510de2118ed7a998a1df9b28fd1be96b4af89ed82c3Behdad Esfahbod  {
51141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
512b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod    return_trace (c->check_struct (this) &&
513b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  likely (version == 0) &&
514b47159011ca518c3b94d782ed16a91ffe9dd2ab2Behdad Esfahbod		  encodingRecord.sanitize (c, this));
51541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
51641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
517f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  USHORT		version;	/* Table version number (0). */
518df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod  SortedArrayOf<EncodingRecord>
519f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod			encodingRecord;	/* Encoding tables. */
52041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
52141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (4, encodingRecord);
52241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
52341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
52441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
52541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod} /* namespace OT */
52641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
52741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
52841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif /* HB_OT_CMAP_TABLE_HH */
529