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