Bug 1601406 [wpt PR 20618] - Advertise DocumentPolicy & Network Err when receive...
[gecko.git] / gfx / ots / src / ots.h
blob4d2be16898c15ed5fdfb2d92ae385b4be5a7c4f8
1 // Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef OTS_H_
6 #define OTS_H_
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <stddef.h>
13 #include <cstdarg>
14 #include <cstddef>
15 #include <cstdio>
16 #include <cstdlib>
17 #include <cstring>
18 #include <limits>
19 #include <map>
21 #include "opentype-sanitiser.h"
23 // arraysize borrowed from base/basictypes.h
24 template <typename T, size_t N>
25 char (&ArraySizeHelper(T (&array)[N]))[N];
26 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
28 namespace ots {
30 #if !defined(OTS_DEBUG)
31 #define OTS_FAILURE() false
32 #else
33 #define OTS_FAILURE() \
35 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
36 __FILE__, __LINE__, __FUNCTION__) \
37 && false\
39 #endif
41 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
42 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
43 // its result (indicating a failure).
45 #if !defined(OTS_DEBUG)
46 #define OTS_MESSAGE_(level,otf_,...) \
47 (otf_)->context->Message(level,__VA_ARGS__)
48 #else
49 #define OTS_MESSAGE_(level,otf_,...) \
50 OTS_FAILURE(), \
51 (otf_)->context->Message(level,__VA_ARGS__)
52 #endif
54 // Generate a simple message
55 #define OTS_FAILURE_MSG_(otf_,...) \
56 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
58 #define OTS_WARNING_MSG_(otf_,...) \
59 OTS_MESSAGE_(1,otf_,__VA_ARGS__)
61 // Convenience macros for use in files that only handle a single table tag,
62 // defined as TABLE_NAME at the top of the file; the 'file' variable is
63 // expected to be the current FontFile pointer.
64 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
66 #define OTS_WARNING(...) OTS_WARNING_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__)
68 // -----------------------------------------------------------------------------
69 // Buffer helper class
71 // This class perform some trival buffer operations while checking for
72 // out-of-bounds errors. As a family they return false if anything is amiss,
73 // updating the current offset otherwise.
74 // -----------------------------------------------------------------------------
75 class Buffer {
76 public:
77 Buffer(const uint8_t *buf, size_t len)
78 : buffer_(buf),
79 length_(len),
80 offset_(0) { }
82 bool Skip(size_t n_bytes) {
83 return Read(NULL, n_bytes);
86 bool Read(uint8_t *buf, size_t n_bytes) {
87 if (n_bytes > 1024 * 1024 * 1024) {
88 return OTS_FAILURE();
90 if ((offset_ + n_bytes > length_) ||
91 (offset_ > length_ - n_bytes)) {
92 return OTS_FAILURE();
94 if (buf) {
95 std::memcpy(buf, buffer_ + offset_, n_bytes);
97 offset_ += n_bytes;
98 return true;
101 inline bool ReadU8(uint8_t *value) {
102 if (offset_ + 1 > length_) {
103 return OTS_FAILURE();
105 *value = buffer_[offset_];
106 ++offset_;
107 return true;
110 bool ReadU16(uint16_t *value) {
111 if (offset_ + 2 > length_) {
112 return OTS_FAILURE();
114 std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
115 *value = ots_ntohs(*value);
116 offset_ += 2;
117 return true;
120 bool ReadS16(int16_t *value) {
121 return ReadU16(reinterpret_cast<uint16_t*>(value));
124 bool ReadU24(uint32_t *value) {
125 if (offset_ + 3 > length_) {
126 return OTS_FAILURE();
128 *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
129 static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
130 static_cast<uint32_t>(buffer_[offset_ + 2]);
131 offset_ += 3;
132 return true;
135 bool ReadU32(uint32_t *value) {
136 if (offset_ + 4 > length_) {
137 return OTS_FAILURE();
139 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
140 *value = ots_ntohl(*value);
141 offset_ += 4;
142 return true;
145 bool ReadS32(int32_t *value) {
146 return ReadU32(reinterpret_cast<uint32_t*>(value));
149 bool ReadR64(uint64_t *value) {
150 if (offset_ + 8 > length_) {
151 return OTS_FAILURE();
153 std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
154 offset_ += 8;
155 return true;
158 const uint8_t *buffer() const { return buffer_; }
159 size_t offset() const { return offset_; }
160 size_t length() const { return length_; }
161 size_t remaining() const { return length_ - offset_; }
163 void set_offset(size_t newoffset) { offset_ = newoffset; }
165 private:
166 const uint8_t * const buffer_;
167 const size_t length_;
168 size_t offset_;
171 // Round a value up to the nearest multiple of 4. Don't round the value in the
172 // case that rounding up overflows.
173 template<typename T> T Round4(T value) {
174 if (std::numeric_limits<T>::max() - value < 3) {
175 return value;
177 return (value + 3) & ~3;
180 template<typename T> T Round2(T value) {
181 if (value == std::numeric_limits<T>::max()) {
182 return value;
184 return (value + 1) & ~1;
187 // Check that a tag consists entirely of printable ASCII characters
188 bool CheckTag(uint32_t tag_value);
190 bool IsValidVersionTag(uint32_t tag);
192 #define OTS_TAG_CFF OTS_TAG('C','F','F',' ')
193 #define OTS_TAG_CFF2 OTS_TAG('C','F','F','2')
194 #define OTS_TAG_CMAP OTS_TAG('c','m','a','p')
195 #define OTS_TAG_CVT OTS_TAG('c','v','t',' ')
196 #define OTS_TAG_FEAT OTS_TAG('F','e','a','t')
197 #define OTS_TAG_FPGM OTS_TAG('f','p','g','m')
198 #define OTS_TAG_GASP OTS_TAG('g','a','s','p')
199 #define OTS_TAG_GDEF OTS_TAG('G','D','E','F')
200 #define OTS_TAG_GLAT OTS_TAG('G','l','a','t')
201 #define OTS_TAG_GLOC OTS_TAG('G','l','o','c')
202 #define OTS_TAG_GLYF OTS_TAG('g','l','y','f')
203 #define OTS_TAG_GPOS OTS_TAG('G','P','O','S')
204 #define OTS_TAG_GSUB OTS_TAG('G','S','U','B')
205 #define OTS_TAG_HDMX OTS_TAG('h','d','m','x')
206 #define OTS_TAG_HEAD OTS_TAG('h','e','a','d')
207 #define OTS_TAG_HHEA OTS_TAG('h','h','e','a')
208 #define OTS_TAG_HMTX OTS_TAG('h','m','t','x')
209 #define OTS_TAG_KERN OTS_TAG('k','e','r','n')
210 #define OTS_TAG_LOCA OTS_TAG('l','o','c','a')
211 #define OTS_TAG_LTSH OTS_TAG('L','T','S','H')
212 #define OTS_TAG_MATH OTS_TAG('M','A','T','H')
213 #define OTS_TAG_MAXP OTS_TAG('m','a','x','p')
214 #define OTS_TAG_NAME OTS_TAG('n','a','m','e')
215 #define OTS_TAG_OS2 OTS_TAG('O','S','/','2')
216 #define OTS_TAG_POST OTS_TAG('p','o','s','t')
217 #define OTS_TAG_PREP OTS_TAG('p','r','e','p')
218 #define OTS_TAG_SILE OTS_TAG('S','i','l','e')
219 #define OTS_TAG_SILF OTS_TAG('S','i','l','f')
220 #define OTS_TAG_SILL OTS_TAG('S','i','l','l')
221 #define OTS_TAG_VDMX OTS_TAG('V','D','M','X')
222 #define OTS_TAG_VHEA OTS_TAG('v','h','e','a')
223 #define OTS_TAG_VMTX OTS_TAG('v','m','t','x')
224 #define OTS_TAG_VORG OTS_TAG('V','O','R','G')
226 #define OTS_TAG_AVAR OTS_TAG('a','v','a','r')
227 #define OTS_TAG_CVAR OTS_TAG('c','v','a','r')
228 #define OTS_TAG_FVAR OTS_TAG('f','v','a','r')
229 #define OTS_TAG_GVAR OTS_TAG('g','v','a','r')
230 #define OTS_TAG_HVAR OTS_TAG('H','V','A','R')
231 #define OTS_TAG_MVAR OTS_TAG('M','V','A','R')
232 #define OTS_TAG_VVAR OTS_TAG('V','V','A','R')
233 #define OTS_TAG_STAT OTS_TAG('S','T','A','T')
235 struct Font;
236 struct FontFile;
237 struct TableEntry;
238 struct Arena;
240 class Table {
241 public:
242 explicit Table(Font *font, uint32_t tag, uint32_t type)
243 : m_tag(tag),
244 m_type(type),
245 m_font(font),
246 m_shouldSerialize(true) {
249 virtual ~Table() { }
251 virtual bool Parse(const uint8_t *data, size_t length) = 0;
252 virtual bool Serialize(OTSStream *out) = 0;
253 virtual bool ShouldSerialize();
255 // Return the tag (table type) this Table was parsed as, to support
256 // "poor man's RTTI" so that we know if we can safely down-cast to
257 // a specific Table subclass. The m_type field is initialized to the
258 // appropriate tag when a subclass is constructed, or to zero for
259 // TablePassthru (indicating unparsed data).
260 uint32_t Type() { return m_type; }
262 Font* GetFont() { return m_font; }
264 bool Error(const char *format, ...);
265 bool Warning(const char *format, ...);
266 bool Drop(const char *format, ...);
267 bool DropGraphite(const char *format, ...);
268 bool DropVariations(const char *format, ...);
270 private:
271 void Message(int level, const char *format, va_list va);
273 uint32_t m_tag;
274 uint32_t m_type;
275 Font *m_font;
276 bool m_shouldSerialize;
279 class TablePassthru : public Table {
280 public:
281 explicit TablePassthru(Font *font, uint32_t tag)
282 : Table(font, tag, 0),
283 m_data(NULL),
284 m_length(0) {
287 bool Parse(const uint8_t *data, size_t length);
288 bool Serialize(OTSStream *out);
290 private:
291 const uint8_t *m_data;
292 size_t m_length;
295 struct Font {
296 explicit Font(FontFile *f)
297 : file(f),
298 version(0),
299 num_tables(0),
300 search_range(0),
301 entry_selector(0),
302 range_shift(0),
303 dropped_graphite(false),
304 dropped_variations(false) {
307 bool ParseTable(const TableEntry& tableinfo, const uint8_t* data,
308 Arena &arena);
309 Table* GetTable(uint32_t tag) const;
311 // This checks that the returned Table is actually of the correct subclass
312 // for |tag|, so it can safely be downcast to the corresponding OpenTypeXXXX;
313 // if not (i.e. if the table was treated as Passthru), it will return NULL.
314 Table* GetTypedTable(uint32_t tag) const;
316 // Drop all Graphite tables and don't parse new ones.
317 void DropGraphite();
319 // Drop all Variations tables and don't parse new ones.
320 void DropVariations();
322 FontFile *file;
324 uint32_t version;
325 uint16_t num_tables;
326 uint16_t search_range;
327 uint16_t entry_selector;
328 uint16_t range_shift;
329 bool dropped_graphite;
330 bool dropped_variations;
332 private:
333 std::map<uint32_t, Table*> m_tables;
336 struct TableEntry {
337 uint32_t tag;
338 uint32_t offset;
339 uint32_t length;
340 uint32_t uncompressed_length;
341 uint32_t chksum;
343 bool operator<(const TableEntry& other) const {
344 return tag < other.tag;
348 struct FontFile {
349 ~FontFile();
351 OTSContext *context;
352 std::map<TableEntry, Table*> tables;
353 std::map<uint32_t, TableEntry> table_entries;
356 } // namespace ots
358 #endif // OTS_H_