|
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. |
|
4 |
|
5 #ifndef OTS_H_ |
|
6 #define OTS_H_ |
|
7 |
|
8 #include <stddef.h> |
|
9 #include <cstdarg> |
|
10 #include <cstddef> |
|
11 #include <cstdio> |
|
12 #include <cstdlib> |
|
13 #include <cstring> |
|
14 #include <limits> |
|
15 |
|
16 #include "opentype-sanitiser.h" |
|
17 |
|
18 // arraysize borrowed from base/basictypes.h |
|
19 template <typename T, size_t N> |
|
20 char (&ArraySizeHelper(T (&array)[N]))[N]; |
|
21 #define arraysize(array) (sizeof(ArraySizeHelper(array))) |
|
22 |
|
23 namespace ots { |
|
24 |
|
25 #if defined(_MSC_VER) || !defined(OTS_DEBUG) |
|
26 #define OTS_FAILURE() false |
|
27 #else |
|
28 #define OTS_FAILURE() ots::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__) |
|
29 bool Failure(const char *f, int l, const char *fn); |
|
30 #endif |
|
31 |
|
32 #if defined(_MSC_VER) |
|
33 // MSVC supports C99 style variadic macros. |
|
34 #define OTS_WARNING(format, ...) |
|
35 #else |
|
36 // GCC |
|
37 #if defined(OTS_DEBUG) |
|
38 #define OTS_WARNING(format, args...) \ |
|
39 ots::Warning(__FILE__, __LINE__, format, ##args) |
|
40 void Warning(const char *f, int l, const char *format, ...) |
|
41 __attribute__((format(printf, 3, 4))); |
|
42 #else |
|
43 #define OTS_WARNING(format, args...) |
|
44 #endif |
|
45 #endif |
|
46 |
|
47 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original |
|
48 // message-less OTS_FAILURE(), so that the current parser will return 'false' as |
|
49 // its result (indicating a failure). |
|
50 // If a message_func pointer has been provided, this will be called before returning |
|
51 // the 'false' status. |
|
52 |
|
53 // Generate a simple message |
|
54 #define OTS_FAILURE_MSG_(otf_,...) \ |
|
55 ((otf_)->message_func && \ |
|
56 (*(otf_)->message_func)((otf_)->user_data, __VA_ARGS__) && \ |
|
57 false) |
|
58 |
|
59 // Generate a message with an associated table tag |
|
60 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \ |
|
61 ((otf_)->message_func && \ |
|
62 (*(otf_)->message_func)((otf_)->user_data, "%4.4s: %s", tag_, msg_) && \ |
|
63 false) |
|
64 |
|
65 // Convenience macro for use in files that only handle a single table tag, |
|
66 // defined as TABLE_NAME at the top of the file; the 'file' variable is |
|
67 // expected to be the current OpenTypeFile pointer. |
|
68 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__) |
|
69 |
|
70 // Define OTS_NO_TRANSCODE_HINTS (i.e., g++ -DOTS_NO_TRANSCODE_HINTS) if you |
|
71 // want to omit TrueType hinting instructions and variables in glyf, fpgm, prep, |
|
72 // and cvt tables. |
|
73 #if defined(OTS_NO_TRANSCODE_HINTS) |
|
74 const bool g_transcode_hints = false; |
|
75 #else |
|
76 const bool g_transcode_hints = true; |
|
77 #endif |
|
78 |
|
79 // ----------------------------------------------------------------------------- |
|
80 // Buffer helper class |
|
81 // |
|
82 // This class perform some trival buffer operations while checking for |
|
83 // out-of-bounds errors. As a family they return false if anything is amiss, |
|
84 // updating the current offset otherwise. |
|
85 // ----------------------------------------------------------------------------- |
|
86 class Buffer { |
|
87 public: |
|
88 Buffer(const uint8_t *buf, size_t len) |
|
89 : buffer_(buf), |
|
90 length_(len), |
|
91 offset_(0) { } |
|
92 |
|
93 bool Skip(size_t n_bytes) { |
|
94 return Read(NULL, n_bytes); |
|
95 } |
|
96 |
|
97 bool Read(uint8_t *buf, size_t n_bytes) { |
|
98 if (n_bytes > 1024 * 1024 * 1024) { |
|
99 return OTS_FAILURE(); |
|
100 } |
|
101 if ((offset_ + n_bytes > length_) || |
|
102 (offset_ > length_ - n_bytes)) { |
|
103 return OTS_FAILURE(); |
|
104 } |
|
105 if (buf) { |
|
106 std::memcpy(buf, buffer_ + offset_, n_bytes); |
|
107 } |
|
108 offset_ += n_bytes; |
|
109 return true; |
|
110 } |
|
111 |
|
112 inline bool ReadU8(uint8_t *value) { |
|
113 if (offset_ + 1 > length_) { |
|
114 return OTS_FAILURE(); |
|
115 } |
|
116 *value = buffer_[offset_]; |
|
117 ++offset_; |
|
118 return true; |
|
119 } |
|
120 |
|
121 bool ReadU16(uint16_t *value) { |
|
122 if (offset_ + 2 > length_) { |
|
123 return OTS_FAILURE(); |
|
124 } |
|
125 std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); |
|
126 *value = ntohs(*value); |
|
127 offset_ += 2; |
|
128 return true; |
|
129 } |
|
130 |
|
131 bool ReadS16(int16_t *value) { |
|
132 return ReadU16(reinterpret_cast<uint16_t*>(value)); |
|
133 } |
|
134 |
|
135 bool ReadU24(uint32_t *value) { |
|
136 if (offset_ + 3 > length_) { |
|
137 return OTS_FAILURE(); |
|
138 } |
|
139 *value = static_cast<uint32_t>(buffer_[offset_]) << 16 | |
|
140 static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 | |
|
141 static_cast<uint32_t>(buffer_[offset_ + 2]); |
|
142 offset_ += 3; |
|
143 return true; |
|
144 } |
|
145 |
|
146 bool ReadU32(uint32_t *value) { |
|
147 if (offset_ + 4 > length_) { |
|
148 return OTS_FAILURE(); |
|
149 } |
|
150 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); |
|
151 *value = ntohl(*value); |
|
152 offset_ += 4; |
|
153 return true; |
|
154 } |
|
155 |
|
156 bool ReadS32(int32_t *value) { |
|
157 return ReadU32(reinterpret_cast<uint32_t*>(value)); |
|
158 } |
|
159 |
|
160 bool ReadTag(uint32_t *value) { |
|
161 if (offset_ + 4 > length_) { |
|
162 return OTS_FAILURE(); |
|
163 } |
|
164 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); |
|
165 offset_ += 4; |
|
166 return true; |
|
167 } |
|
168 |
|
169 bool ReadR64(uint64_t *value) { |
|
170 if (offset_ + 8 > length_) { |
|
171 return OTS_FAILURE(); |
|
172 } |
|
173 std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); |
|
174 offset_ += 8; |
|
175 return true; |
|
176 } |
|
177 |
|
178 const uint8_t *buffer() const { return buffer_; } |
|
179 size_t offset() const { return offset_; } |
|
180 size_t length() const { return length_; } |
|
181 |
|
182 void set_offset(size_t newoffset) { offset_ = newoffset; } |
|
183 |
|
184 private: |
|
185 const uint8_t * const buffer_; |
|
186 const size_t length_; |
|
187 size_t offset_; |
|
188 }; |
|
189 |
|
190 // Round a value up to the nearest multiple of 4. Don't round the value in the |
|
191 // case that rounding up overflows. |
|
192 template<typename T> T Round4(T value) { |
|
193 if (std::numeric_limits<T>::max() - value < 3) { |
|
194 return value; |
|
195 } |
|
196 return (value + 3) & ~3; |
|
197 } |
|
198 |
|
199 template<typename T> T Round2(T value) { |
|
200 if (value == std::numeric_limits<T>::max()) { |
|
201 return value; |
|
202 } |
|
203 return (value + 1) & ~1; |
|
204 } |
|
205 |
|
206 bool IsValidVersionTag(uint32_t tag); |
|
207 |
|
208 #define FOR_EACH_TABLE_TYPE \ |
|
209 F(cff, CFF) \ |
|
210 F(cmap, CMAP) \ |
|
211 F(cvt, CVT) \ |
|
212 F(fpgm, FPGM) \ |
|
213 F(gasp, GASP) \ |
|
214 F(gdef, GDEF) \ |
|
215 F(glyf, GLYF) \ |
|
216 F(gpos, GPOS) \ |
|
217 F(gsub, GSUB) \ |
|
218 F(hdmx, HDMX) \ |
|
219 F(head, HEAD) \ |
|
220 F(hhea, HHEA) \ |
|
221 F(hmtx, HMTX) \ |
|
222 F(kern, KERN) \ |
|
223 F(loca, LOCA) \ |
|
224 F(ltsh, LTSH) \ |
|
225 F(math, MATH) \ |
|
226 F(maxp, MAXP) \ |
|
227 F(name, NAME) \ |
|
228 F(os2, OS2) \ |
|
229 F(post, POST) \ |
|
230 F(prep, PREP) \ |
|
231 F(vdmx, VDMX) \ |
|
232 F(vorg, VORG) \ |
|
233 F(vhea, VHEA) \ |
|
234 F(vmtx, VMTX) |
|
235 |
|
236 #define F(name, capname) struct OpenType##capname; |
|
237 FOR_EACH_TABLE_TYPE |
|
238 #undef F |
|
239 |
|
240 struct OpenTypeFile { |
|
241 OpenTypeFile() { |
|
242 #define F(name, capname) name = NULL; |
|
243 FOR_EACH_TABLE_TYPE |
|
244 #undef F |
|
245 } |
|
246 |
|
247 uint32_t version; |
|
248 uint16_t num_tables; |
|
249 uint16_t search_range; |
|
250 uint16_t entry_selector; |
|
251 uint16_t range_shift; |
|
252 |
|
253 MessageFunc message_func; |
|
254 void *user_data; |
|
255 |
|
256 #define F(name, capname) OpenType##capname *name; |
|
257 FOR_EACH_TABLE_TYPE |
|
258 #undef F |
|
259 }; |
|
260 |
|
261 #define F(name, capname) \ |
|
262 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \ |
|
263 bool ots_##name##_should_serialise(OpenTypeFile *f); \ |
|
264 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \ |
|
265 void ots_##name##_free(OpenTypeFile *f); |
|
266 // TODO(yusukes): change these function names to follow Chromium coding rule. |
|
267 FOR_EACH_TABLE_TYPE |
|
268 #undef F |
|
269 |
|
270 } // namespace ots |
|
271 |
|
272 #endif // OTS_H_ |