hb-open-file-private.hh revision e45d3f86f9a5f3d29ca35a282de7f98e702878f9
1/*
2 * Copyright (C) 2007,2008,2009  Red Hat, Inc.
3 *
4 *  This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Red Hat Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_OPEN_FILE_PRIVATE_HH
28#define HB_OPEN_FILE_PRIVATE_HH
29
30#include "hb-open-type-private.hh"
31
32
33/*
34 *
35 * The OpenType Font File
36 *
37 */
38
39
40/*
41 * Organization of an OpenType Font
42 */
43
44struct OpenTypeFontFile;
45struct OffsetTable;
46struct TTCHeader;
47
48typedef struct TableDirectory
49{
50  inline bool sanitize (hb_sanitize_context_t *context) {
51    TRACE_SANITIZE ();
52    return context->check_struct (this);
53  }
54
55  DEFINE_SIZE_STATIC (16);
56
57  Tag		tag;		/* 4-byte identifier. */
58  CheckSum	checkSum;	/* CheckSum for this table. */
59  ULONG		offset;		/* Offset from beginning of TrueType font
60				 * file. */
61  ULONG		length;		/* Length of this table. */
62} OpenTypeTable;
63
64typedef struct OffsetTable
65{
66  friend struct OpenTypeFontFile;
67
68  inline unsigned int get_table_count (void) const
69  { return numTables; }
70  inline const TableDirectory& get_table (unsigned int i) const
71  {
72    if (unlikely (i >= numTables)) return Null(TableDirectory);
73    return tableDir[i];
74  }
75  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
76  {
77    Tag t;
78    t.set (tag);
79    /* TODO: bsearch (need to sort in sanitize) */
80    unsigned int count = numTables;
81    for (unsigned int i = 0; i < count; i++)
82    {
83      if (t == tableDir[i].tag)
84      {
85        if (table_index) *table_index = i;
86        return true;
87      }
88    }
89    if (table_index) *table_index = NO_INDEX;
90    return false;
91  }
92  inline const TableDirectory& get_table_by_tag (hb_tag_t tag) const
93  {
94    unsigned int table_index;
95    find_table_index (tag, &table_index);
96    return get_table (table_index);
97  }
98
99  public:
100  inline bool sanitize (hb_sanitize_context_t *context) {
101    TRACE_SANITIZE ();
102    return context->check_struct (this)
103	&& context->check_array (tableDir, TableDirectory::static_size, numTables);
104  }
105
106  private:
107  Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
108  USHORT	numTables;	/* Number of tables. */
109  USHORT	searchRange;	/* (Maximum power of 2 <= numTables) x 16 */
110  USHORT	entrySelector;	/* Log2(maximum power of 2 <= numTables). */
111  USHORT	rangeShift;	/* NumTables x 16-searchRange. */
112  TableDirectory tableDir[VAR];	/* TableDirectory entries. numTables items */
113} OpenTypeFontFace;
114ASSERT_SIZE_VAR (OffsetTable, 12, TableDirectory);
115
116/*
117 * TrueType Collections
118 */
119
120struct TTCHeaderVersion1
121{
122  friend struct TTCHeader;
123
124  inline unsigned int get_face_count (void) const { return table.len; }
125  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
126
127  inline bool sanitize (hb_sanitize_context_t *context) {
128    TRACE_SANITIZE ();
129    return table.sanitize (context, this);
130  }
131
132  private:
133  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
134  FixedVersion	version;	/* Version of the TTC Header (1.0),
135				 * 0x00010000 */
136  LongOffsetLongArrayOf<OffsetTable>
137		table;		/* Array of offsets to the OffsetTable for each font
138				 * from the beginning of the file */
139};
140ASSERT_SIZE (TTCHeaderVersion1, 12);
141
142struct TTCHeader
143{
144  friend struct OpenTypeFontFile;
145
146  private:
147
148  inline unsigned int get_face_count (void) const
149  {
150    switch (u.header.version) {
151    case 2: /* version 2 is compatible with version 1 */
152    case 1: return u.version1->get_face_count ();
153    default:return 0;
154    }
155  }
156  inline const OpenTypeFontFace& get_face (unsigned int i) const
157  {
158    switch (u.header.version) {
159    case 2: /* version 2 is compatible with version 1 */
160    case 1: return u.version1->get_face (i);
161    default:return Null(OpenTypeFontFace);
162    }
163  }
164
165  inline bool sanitize (hb_sanitize_context_t *context) {
166    TRACE_SANITIZE ();
167    if (!u.header.version.sanitize (context)) return false;
168    switch (u.header.version) {
169    case 2: /* version 2 is compatible with version 1 */
170    case 1: return u.version1->sanitize (context);
171    default:return true;
172    }
173  }
174
175  private:
176  union {
177  struct {
178  Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
179  FixedVersion	version;	/* Version of the TTC Header (1.0 or 2.0),
180				 * 0x00010000 or 0x00020000 */
181  }			header;
182  TTCHeaderVersion1	version1[VAR];
183  } u;
184};
185
186
187/*
188 * OpenType Font File
189 */
190
191struct OpenTypeFontFile
192{
193  static const hb_tag_t CFFTag		= HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
194  static const hb_tag_t TrueTypeTag	= HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
195  static const hb_tag_t TTCTag		= HB_TAG ('t','t','c','f'); /* TrueType Collection */
196  static const hb_tag_t TrueTag		= HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */
197  static const hb_tag_t Typ1Tag		= HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */
198
199  inline hb_tag_t get_tag (void) const { return u.tag; }
200
201  inline unsigned int get_face_count (void) const
202  {
203    switch (u.tag) {
204    case CFFTag:	/* All the non-collection tags */
205    case TrueTag:
206    case Typ1Tag:
207    case TrueTypeTag:	return 1;
208    case TTCTag:	return u.ttcHeader->get_face_count ();
209    default:		return 0;
210    }
211  }
212  inline const OpenTypeFontFace& get_face (unsigned int i) const
213  {
214    switch (u.tag) {
215    /* Note: for non-collection SFNT data we ignore index.  This is because
216     * Apple dfont container is a container of SFNT's.  So each SFNT is a
217     * non-TTC, but the index is more than zero. */
218    case CFFTag:	/* All the non-collection tags */
219    case TrueTag:
220    case Typ1Tag:
221    case TrueTypeTag:	return u.fontFace[0];
222    case TTCTag:	return u.ttcHeader->get_face (i);
223    default:		return Null(OpenTypeFontFace);
224    }
225  }
226
227  inline bool sanitize (hb_sanitize_context_t *context) {
228    TRACE_SANITIZE ();
229    if (!u.tag.sanitize (context)) return false;
230    switch (u.tag) {
231    case CFFTag:	/* All the non-collection tags */
232    case TrueTag:
233    case Typ1Tag:
234    case TrueTypeTag:	return u.fontFace->sanitize (context);
235    case TTCTag:	return u.ttcHeader->sanitize (context);
236    default:		return true;
237    }
238  }
239
240  private:
241  union {
242  Tag			tag;		/* 4-byte identifier. */
243  OpenTypeFontFace	fontFace[VAR];
244  TTCHeader		ttcHeader[VAR];
245  } u;
246};
247
248
249#endif /* HB_OPEN_FILE_PRIVATE_HH */
250