gfx/ots/src/ots.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f07bc4b9f51c
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_

mercurial