Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / ots / src / ots.h
blobb2dd9ad48d7255b0e98cd43eec033d3205c0f1be
1 // Copyright (c) 2009 The Chromium 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 #include <stddef.h>
9 #include <cstdarg>
10 #include <cstddef>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <limits>
15 #include <map>
17 #include "opentype-sanitiser.h"
19 // arraysize borrowed from base/basictypes.h
20 template <typename T, size_t N>
21 char (&ArraySizeHelper(T (&array)[N]))[N];
22 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
24 namespace ots {
26 #if !defined(OTS_DEBUG)
27 #define OTS_FAILURE() false
28 #else
29 #define OTS_FAILURE() \
31 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
32 __FILE__, __LINE__, __FUNCTION__) \
33 && false\
35 #endif
37 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
38 // message-less OTS_FAILURE(), so that the current parser will return 'false' as
39 // its result (indicating a failure).
41 #if !defined(OTS_DEBUG)
42 #define OTS_MESSAGE_(level,otf_,...) \
43 (otf_)->context->Message(level,__VA_ARGS__)
44 #else
45 #define OTS_MESSAGE_(level,otf_,...) \
46 OTS_FAILURE(), \
47 (otf_)->context->Message(level,__VA_ARGS__)
48 #endif
50 // Generate a simple message
51 #define OTS_FAILURE_MSG_(otf_,...) \
52 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
54 #define OTS_WARNING_MSG_(otf_,...) \
55 OTS_MESSAGE_(1,otf_,__VA_ARGS__)
57 // Generate a message with an associated table tag
58 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
59 (OTS_MESSAGE_(0,otf_,"%c%c%c%c: %s", OTS_UNTAG(tag_), msg_), false)
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 OpenTypeFile 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 = 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 = 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_; }
162 void set_offset(size_t newoffset) { offset_ = newoffset; }
164 private:
165 const uint8_t * const buffer_;
166 const size_t length_;
167 size_t offset_;
170 // Round a value up to the nearest multiple of 4. Don't round the value in the
171 // case that rounding up overflows.
172 template<typename T> T Round4(T value) {
173 if (std::numeric_limits<T>::max() - value < 3) {
174 return value;
176 return (value + 3) & ~3;
179 template<typename T> T Round2(T value) {
180 if (value == std::numeric_limits<T>::max()) {
181 return value;
183 return (value + 1) & ~1;
186 bool IsValidVersionTag(uint32_t tag);
188 #define FOR_EACH_TABLE_TYPE \
189 F(cff, CFF) \
190 F(cmap, CMAP) \
191 F(cvt, CVT) \
192 F(fpgm, FPGM) \
193 F(gasp, GASP) \
194 F(gdef, GDEF) \
195 F(glyf, GLYF) \
196 F(gpos, GPOS) \
197 F(gsub, GSUB) \
198 F(hdmx, HDMX) \
199 F(head, HEAD) \
200 F(hhea, HHEA) \
201 F(hmtx, HMTX) \
202 F(kern, KERN) \
203 F(loca, LOCA) \
204 F(ltsh, LTSH) \
205 F(math, MATH) \
206 F(maxp, MAXP) \
207 F(name, NAME) \
208 F(os2, OS2) \
209 F(post, POST) \
210 F(prep, PREP) \
211 F(vdmx, VDMX) \
212 F(vorg, VORG) \
213 F(vhea, VHEA) \
214 F(vmtx, VMTX)
216 #define F(name, capname) struct OpenType##capname;
217 FOR_EACH_TABLE_TYPE
218 #undef F
220 struct Font;
221 struct OpenTypeFile;
223 #define F(name, capname) \
224 bool ots_##name##_parse(Font *f, const uint8_t *d, size_t l); \
225 bool ots_##name##_should_serialise(Font *f); \
226 bool ots_##name##_serialise(OTSStream *s, Font *f); \
227 void ots_##name##_reuse(Font *f, Font *o);\
228 void ots_##name##_free(Font *f);
229 FOR_EACH_TABLE_TYPE
230 #undef F
232 struct Font {
233 Font(const OpenTypeFile *f) {
234 file = f;
235 #define F(name, capname) \
236 name = NULL; \
237 name##_reused = false;
238 FOR_EACH_TABLE_TYPE
239 #undef F
242 ~Font() {
243 #define F(name, capname) \
244 if (!name##_reused) {\
245 ots_##name##_free(this); \
247 FOR_EACH_TABLE_TYPE
248 #undef F
251 const OpenTypeFile *file;
253 uint32_t version;
254 uint16_t num_tables;
255 uint16_t search_range;
256 uint16_t entry_selector;
257 uint16_t range_shift;
259 #define F(name, capname) \
260 OpenType##capname *name; \
261 bool name##_reused;
262 FOR_EACH_TABLE_TYPE
263 #undef F
266 struct OutputTable {
267 uint32_t tag;
268 size_t offset;
269 size_t length;
270 uint32_t chksum;
272 bool operator<(const OutputTable& other) const {
273 return tag < other.tag;
277 typedef std::map<uint32_t, std::pair<Font*, OutputTable> > TableMap;
279 struct OpenTypeFile {
280 OTSContext *context;
281 TableMap tables;
284 } // namespace ots
286 #undef FOR_EACH_TABLE_TYPE
288 #endif // OTS_H_