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
54b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
55b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    TRACE_SANITIZE (this);
56b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
57b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  }
58b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod
59b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  protected:
60b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  USHORT	format;		/* Format number is set to 0. */
617d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	lengthZ;	/* Byte length of this subtable. */
627d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	languageZ;	/* Ignore. */
63b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  BYTE		glyphIdArray[256];/* An array that maps character
64b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod				 * code to glyph index values. */
65b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  public:
66b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  DEFINE_SIZE_STATIC (6 + 256);
67b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod};
68b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod
6941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct CmapSubtableFormat4
7041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
7141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
7241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
73c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int segCount;
74c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *endCount;
75c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *startCount;
76c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *idDelta;
77c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *idRangeOffset;
78c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    const USHORT *glyphIdArray;
79c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int glyphIdArrayLength;
80c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
81c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    segCount = this->segCountX2 / 2;
82c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    endCount = this->values;
83c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    startCount = endCount + segCount + 1;
84c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    idDelta = startCount + segCount;
85c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    idRangeOffset = idDelta + segCount;
86c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    glyphIdArray = idRangeOffset + segCount;
87c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
88c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
89df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    /* Custom two-array bsearch. */
90c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    int min = 0, max = (int) segCount - 1;
91c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int i;
92c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    while (min <= max)
93c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    {
94c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      int mid = (min + max) / 2;
95c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (codepoint < startCount[mid])
96c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod        max = mid - 1;
97c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      else if (codepoint > endCount[mid])
98c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod        min = mid + 1;
99c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      else
100c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      {
101c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	i = mid;
102c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	goto found;
103c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      }
104c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    }
10541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return false;
106c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
107c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod  found:
108c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    hb_codepoint_t gid;
109c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    unsigned int rangeOffset = idRangeOffset[i];
110c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    if (rangeOffset == 0)
111c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid = codepoint + idDelta[i];
112c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    else
113c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    {
114c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      /* Somebody has been smoking... */
115c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
116c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (unlikely (index >= glyphIdArrayLength))
117c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	return false;
118c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid = glyphIdArray[index];
119c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      if (unlikely (!gid))
120c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod	return false;
121c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod      gid += idDelta[i];
122c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    }
123c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod
1247627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    *glyph = gid & 0xFFFFu;
125c8a47452993b9dee6854bfc866aca4a20142696fBehdad Esfahbod    return true;
12641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
12741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
128257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c)
129257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod  {
13041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
131257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_struct (this)))
132257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      return TRACE_RETURN (false);
133257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
134257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    if (unlikely (!c->check_range (this, length)))
135257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    {
136257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      /* Some broken fonts have too long of a "length" value.
137257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * If that is the case, just change the value to truncate
138257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod       * the subtable at the end of the blob. */
139257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
140257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod					    (uintptr_t) (c->end -
141257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod							 (char *) this));
142257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod      if (!c->try_set (&length, new_length))
143257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod	return TRACE_RETURN (false);
144257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    }
145257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod
146257d1adfa1b3422c511c55e641840a6e31ec6008Behdad Esfahbod    return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length);
14741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
14841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
14941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  protected:
15041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	format;		/* Format number is set to 4. */
15141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	length;		/* This is the length in bytes of the
15241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod				 * subtable. */
1537d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	languageZ;	/* Ignore. */
15441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	segCountX2;	/* 2 x segCount. */
1557d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	searchRangeZ;	/* 2 * (2**floor(log2(segCount))) */
1567d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	entrySelectorZ;	/* log2(searchRange/2) */
1577d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	rangeShiftZ;	/* 2 x segCount - searchRange */
15841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
15941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	values[VAR];
16041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#if 0
16141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	endCount[segCount];	/* End characterCode for each segment,
1627627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod					 * last=0xFFFFu. */
16341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	reservedPad;		/* Set to 0. */
16441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	startCount[segCount];	/* Start character code for each segment. */
16541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  SHORT		idDelta[segCount];	/* Delta for all character codes in segment. */
16641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
16741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	glyphIdArray[VAR];	/* Glyph index array (arbitrary length) */
16841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif
16941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
17041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
17141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (14, values);
17241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
17341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
174d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbodstruct CmapSubtableLongGroup
1750d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
1760d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  friend struct CmapSubtableFormat12;
177d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  friend struct CmapSubtableFormat13;
1780d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1790d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  int cmp (hb_codepoint_t codepoint) const
1800d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
1810d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint < startCharCode) return -1;
1820d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (codepoint > endCharCode)   return +1;
1830d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return 0;
1840d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
1850d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1860d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1870d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
1880d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
1890d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
1900d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
1910d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  private:
1920d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		startCharCode;	/* First character code in this group. */
1930d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  ULONG		endCharCode;	/* Last character code in this group. */
194d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  ULONG		glyphID;	/* Glyph index; interpretation depends on
195d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod				 * subtable format. */
1960d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  public:
1970d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  DEFINE_SIZE_STATIC (12);
1980d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
1990d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
20094759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodtemplate <typename UINT>
20194759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableTrimmed
20291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod{
20391bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
20491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  {
20591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    /* Rely on our implicit array bound-checking. */
20691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
20791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    if (!gid)
20891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod      return false;
20991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    *glyph = gid;
21091bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    return true;
21191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
21291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
21391bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
21491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    TRACE_SANITIZE (this);
21591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c));
21691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  }
21791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
21891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  protected:
21994759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		formatReserved;	/* Subtable format and (maybe) padding. */
2207d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		lengthZ;	/* Byte length of this subtable. */
2217d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  UINT		languageZ;	/* Ignore. */
22294759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  UINT		startCharCode;	/* First character code covered. */
2239da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod  ArrayOf<GlyphID, UINT>
22491bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod		glyphIdArray;	/* Array of glyph index values for character
22591bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod				 * codes in the range. */
22691bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  public:
22794759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbod  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
22891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod};
22991bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
23094759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat6  : CmapSubtableTrimmed<USHORT> {};
23194759e8219ed08392573bae948a8135e16b8e0d0Behdad Esfahbodstruct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {};
23291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod
233ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodtemplate <typename T>
234ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableLongSegmented
2350d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod{
2360d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
2370d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  {
238df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int i = groups.bsearch (codepoint);
2390d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    if (i == -1)
2400d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod      return false;
241ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod    *glyph = T::group_get_glyph (groups[i], codepoint);
2420d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return true;
2430d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2440d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
2450d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2460d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    TRACE_SANITIZE (this);
2470d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c));
2480d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  }
2490d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
2500d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  protected:
2510d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  USHORT	format;		/* Subtable format; set to 12. */
2527d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  USHORT	reservedZ;	/* Reserved; set to 0. */
2537d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
2547d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		languageZ;	/* Ignore. */
25541ea59495032e712fa6f801350ee00d5f00b5724Behdad Esfahbod  SortedArrayOf<CmapSubtableLongGroup, ULONG>
256d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod		groups;		/* Groupings. */
257d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  public:
258d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  DEFINE_SIZE_ARRAY (16, groups);
259d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod};
260d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
261ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
262d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod{
263ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
264ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u)
265ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID + (u - group.startCharCode); }
266ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod};
267d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod
268ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbodstruct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
269ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod{
270ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
271ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod						hb_codepoint_t u HB_UNUSED)
272ca7b77431d1e0aaa803722be8be85a368a385f47Behdad Esfahbod  { return group.glyphID; }
2730d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod};
2740d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod
275a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef enum
276a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
277a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_NOT_FOUND = 0,
278a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_FOUND = 1,
279a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GLYPH_VARIANT_USE_DEFAULT = 2
280a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod} glyph_variant_t;
281a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
282a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UnicodeValueRange
283a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
284a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
285a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
286a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint < startUnicodeValue) return -1;
287a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (codepoint > startUnicodeValue + additionalCount) return +1;
288a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return 0;
289a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
290a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
291a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
292a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
293a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
294a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
295a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
296a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	startUnicodeValue;	/* First value in this range. */
297a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  BYTE		additionalCount;	/* Number of additional values in this
298a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					 * range. */
299a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
300a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (4);
301a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
302a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
303a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS;
304a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
305a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct UVSMapping
306a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
307a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &codepoint) const
308a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
309a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return unicodeValue.cmp (codepoint);
310a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
311a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
312a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
313a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
314a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
315a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
316a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
317a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	unicodeValue;	/* Base Unicode value of the UVS */
318a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  GlyphID	glyphID;	/* Glyph ID of the UVS */
319a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
320a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (5);
321a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
322a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
323a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodtypedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS;
324a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
325a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct VariationSelectorRecord
326a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
327a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
328a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    hb_codepoint_t *glyph,
329a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				    const void *base) const
330a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
331a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    int i;
332a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const DefaultUVS &defaults = base+defaultUVS;
333a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = defaults.bsearch (codepoint);
334a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
335a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      return GLYPH_VARIANT_USE_DEFAULT;
336a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
337a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    i = nonDefaults.bsearch (codepoint);
338a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    if (i != -1)
339a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    {
340a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod      *glyph = nonDefaults[i].glyphID;
341a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod       return GLYPH_VARIANT_FOUND;
342a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
343a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return GLYPH_VARIANT_NOT_FOUND;
344a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
345a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
346a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline int cmp (const hb_codepoint_t &variation_selector) const
347a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
348a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return varSelector.cmp (variation_selector);
349a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
350a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
351a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
352a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
353a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this) &&
354a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 defaultUVS.sanitize (c, base) &&
355a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 nonDefaultUVS.sanitize (c, base));
356a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
357a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
358a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  UINT24	varSelector;	/* Variation selector. */
359a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  OffsetTo<DefaultUVS, ULONG>
360a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		defaultUVS;	/* Offset to Default UVS Table. May be 0. */
361a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  OffsetTo<NonDefaultUVS, ULONG>
362a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		nonDefaultUVS;	/* Offset to Non-Default UVS Table. May be 0. */
363a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
364a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_STATIC (11);
365a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
366a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
367a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbodstruct CmapSubtableFormat14
368a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod{
369a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
370a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t variation_selector,
371a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t *glyph) const
372a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
373a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
374a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
375a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
376a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
377a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    TRACE_SANITIZE (this);
378a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this) &&
379a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 record.sanitize (c, this));
380a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
381a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
382a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  protected:
383a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  USHORT	format;		/* Format number is set to 0. */
3847d4ada66c96a748ce92f8e8edac149361c3dc829Behdad Esfahbod  ULONG		lengthZ;	/* Byte length of this subtable. */
385a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  SortedArrayOf<VariationSelectorRecord, ULONG>
386a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod		record;		/* Variation selector records; sorted
387a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod				 * in increasing order of `varSelector'. */
388a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  public:
389a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  DEFINE_SIZE_ARRAY (10, record);
390a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod};
391a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
39241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct CmapSubtable
39341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
394c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
395c95587618c88d187be64f923033dae151cf820beBehdad Esfahbod
396a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline bool get_glyph (hb_codepoint_t codepoint,
397a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod			 hb_codepoint_t *glyph) const
39841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
39941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
400b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    case  0: return u.format0 .get_glyph(codepoint, glyph);
4010d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case  4: return u.format4 .get_glyph(codepoint, glyph);
40291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case  6: return u.format6 .get_glyph(codepoint, glyph);
40391bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case 10: return u.format10.get_glyph(codepoint, glyph);
4040d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case 12: return u.format12.get_glyph(codepoint, glyph);
405d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod    case 13: return u.format13.get_glyph(codepoint, glyph);
406a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    case 14:
407a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    default: return false;
408a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    }
409a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  }
410a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod
411a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
412a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t variation_selector,
413a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod					    hb_codepoint_t *glyph) const
414a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  {
415a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    switch (u.format) {
416a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
417a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod    default: return GLYPH_VARIANT_NOT_FOUND;
41841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    }
41941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
42041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
42141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
42241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
42341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
42441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    switch (u.format) {
425b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod    case  0: return TRACE_RETURN (u.format0 .sanitize (c));
4260d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case  4: return TRACE_RETURN (u.format4 .sanitize (c));
42791bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case  6: return TRACE_RETURN (u.format6 .sanitize (c));
42891bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod    case 10: return TRACE_RETURN (u.format10.sanitize (c));
4290d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod    case 12: return TRACE_RETURN (u.format12.sanitize (c));
430d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod    case 13: return TRACE_RETURN (u.format13.sanitize (c));
431af528b6674bccac3efd13f8b33fcdc6aeb178f4cBehdad Esfahbod    case 14: return TRACE_RETURN (u.format14.sanitize (c));
43241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    default:return TRACE_RETURN (true);
43341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    }
43441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
43541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
43641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  protected:
43741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  union {
43841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT		format;		/* Format identifier */
439b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbod  CmapSubtableFormat0	format0;
44041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  CmapSubtableFormat4	format4;
44191bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat6	format6;
44291bbfca87527fa14d6ebec86b087f2a989381872Behdad Esfahbod  CmapSubtableFormat10	format10;
4430d75793fae95ed9f6b8522ae3af4fcdf397d8c36Behdad Esfahbod  CmapSubtableFormat12	format12;
444d294a2cb165c4f20daa5624969067c51eb9aef58Behdad Esfahbod  CmapSubtableFormat13	format13;
445a5a4736916b6035e6413d4619f9e7287e683d51bBehdad Esfahbod  CmapSubtableFormat14	format14;
44641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  } u;
44741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
44841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_UNION (2, format);
44941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
45041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
45141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
45241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct EncodingRecord
45341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
454f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  inline int cmp (const EncodingRecord &other) const
45541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
45641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    int ret;
457f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = platformID.cmp (other.platformID);
45841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
459f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod    ret = encodingID.cmp (other.encodingID);
46041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    if (ret) return ret;
46141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return 0;
46241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
46341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
46441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
46541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
46641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return TRACE_RETURN (c->check_struct (this) &&
46741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod			 subtable.sanitize (c, base));
46841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
46941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
47041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	platformID;	/* Platform ID. */
47141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  USHORT	encodingID;	/* Platform-specific encoding ID. */
4729da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod  OffsetTo<CmapSubtable, ULONG>
47341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod		subtable;	/* Byte offset from beginning of table to the subtable for this encoding. */
47441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
47541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_STATIC (8);
47641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
47741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
47841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbodstruct cmap
47941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod{
48041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  static const hb_tag_t tableTag	= HB_OT_TAG_cmap;
48141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
4823608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod  inline const CmapSubtable *find_subtable (unsigned int platform_id,
4833608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod					    unsigned int encoding_id) const
48441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  {
48541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    EncodingRecord key;
48641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.platformID.set (platform_id);
48741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    key.encodingID.set (encoding_id);
48841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
489df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    /* Note: We can use bsearch, but since it has no performance
490df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * implications, we use lsearch and as such accept fonts with
491df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod     * unsorted subtable list. */
492df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod    int result = encodingRecord./*bsearch*/lsearch (key);
493500737e8e16dce5248aff394899bb3761a9c3bbfBehdad Esfahbod    if (result == -1 || !encodingRecord[result].subtable)
4943608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod      return NULL;
4953608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod
4963608a6847e7b7eb4206df049158513a085810afdBehdad Esfahbod    return &(this+encodingRecord[result].subtable);
49741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
49841ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
49941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
50041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    TRACE_SANITIZE (this);
50141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod    return TRACE_RETURN (c->check_struct (this) &&
50241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod			 likely (version == 0) &&
50341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod			 encodingRecord.sanitize (c, this));
50441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  }
50541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
506f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod  USHORT		version;	/* Table version number (0). */
507df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod  SortedArrayOf<EncodingRecord>
508f1a72fe7bf863535ec09b559cc0bd878fd0799f2Behdad Esfahbod			encodingRecord;	/* Encoding tables. */
50941ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  public:
51041ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod  DEFINE_SIZE_ARRAY (4, encodingRecord);
51141ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod};
51241ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
51341ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
51441ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod} /* namespace OT */
51541ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
51641ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod
51741ca1fbebf61cf26e1e0e4b11f4a5b52fb7d88a9Behdad Esfahbod#endif /* HB_OT_CMAP_TABLE_HH */
518