blob: 1db48d51736bcd114ed2bcb5f49210f15eb16b64 [file] [log] [blame]
yusukes@chromium.orgd257d182009-11-04 04:56:32 +00001// 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
yusukes@chromium.org7f9bebe2011-06-07 05:25:38 +00008#include <stddef.h>
yusukes@chromium.orgd257d182009-11-04 04:56:32 +00009#include <cstdarg>
bashi@chromium.orgcd35d032011-05-31 07:38:53 +000010#include <cstddef>
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000011#include <cstdio>
12#include <cstdlib>
13#include <cstring>
ksakamoto@chromium.org74343ba2013-05-08 01:20:29 +000014#include <limits>
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000015
16#include "opentype-sanitiser.h"
17
ksakamoto@chromium.org74343ba2013-05-08 01:20:29 +000018// arraysize borrowed from base/basictypes.h
19template <typename T, size_t N>
20char (&ArraySizeHelper(T (&array)[N]))[N];
21#define arraysize(array) (sizeof(ArraySizeHelper(array)))
22
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000023namespace 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__)
29bool 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)
40void 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// Define OTS_NO_TRANSCODE_HINTS (i.e., g++ -DOTS_NO_TRANSCODE_HINTS) if you
48// want to omit TrueType hinting instructions and variables in glyf, fpgm, prep,
49// and cvt tables.
50#if defined(OTS_NO_TRANSCODE_HINTS)
51const bool g_transcode_hints = false;
52#else
53const bool g_transcode_hints = true;
54#endif
55
56// -----------------------------------------------------------------------------
57// Buffer helper class
58//
59// This class perform some trival buffer operations while checking for
60// out-of-bounds errors. As a family they return false if anything is amiss,
61// updating the current offset otherwise.
62// -----------------------------------------------------------------------------
63class Buffer {
64 public:
65 Buffer(const uint8_t *buffer, size_t len)
66 : buffer_(buffer),
67 length_(len),
68 offset_(0) { }
69
70 bool Skip(size_t n_bytes) {
71 return Read(NULL, n_bytes);
72 }
73
74 bool Read(uint8_t *buffer, size_t n_bytes) {
75 if (n_bytes > 1024 * 1024 * 1024) {
76 return OTS_FAILURE();
77 }
78 if ((offset_ + n_bytes > length_) ||
79 (offset_ > length_ - n_bytes)) {
80 return OTS_FAILURE();
81 }
82 if (buffer) {
83 std::memcpy(buffer, buffer_ + offset_, n_bytes);
84 }
85 offset_ += n_bytes;
86 return true;
87 }
88
89 inline bool ReadU8(uint8_t *value) {
90 if (offset_ + 1 > length_) {
91 return OTS_FAILURE();
92 }
93 *value = buffer_[offset_];
94 ++offset_;
95 return true;
96 }
97
98 bool ReadU16(uint16_t *value) {
99 if (offset_ + 2 > length_) {
100 return OTS_FAILURE();
101 }
102 std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
103 *value = ntohs(*value);
104 offset_ += 2;
105 return true;
106 }
107
108 bool ReadS16(int16_t *value) {
109 return ReadU16(reinterpret_cast<uint16_t*>(value));
110 }
111
bashi@google.com93aedf72010-12-24 00:29:23 +0000112 bool ReadU24(uint32_t *value) {
113 if (offset_ + 3 > length_) {
114 return OTS_FAILURE();
115 }
116 *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
117 static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
118 static_cast<uint32_t>(buffer_[offset_ + 2]);
119 offset_ += 3;
120 return true;
121 }
122
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000123 bool ReadU32(uint32_t *value) {
124 if (offset_ + 4 > length_) {
125 return OTS_FAILURE();
126 }
127 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
128 *value = ntohl(*value);
129 offset_ += 4;
130 return true;
131 }
132
133 bool ReadS32(int32_t *value) {
134 return ReadU32(reinterpret_cast<uint32_t*>(value));
135 }
136
137 bool ReadTag(uint32_t *value) {
138 if (offset_ + 4 > length_) {
139 return OTS_FAILURE();
140 }
141 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
142 offset_ += 4;
143 return true;
144 }
145
146 bool ReadR64(uint64_t *value) {
147 if (offset_ + 8 > length_) {
148 return OTS_FAILURE();
149 }
150 std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
151 offset_ += 8;
152 return true;
153 }
154
yusukes@chromium.org6263d062010-08-06 03:27:28 +0000155 const uint8_t *buffer() const { return buffer_; }
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000156 size_t offset() const { return offset_; }
157 size_t length() const { return length_; }
158
159 void set_offset(size_t newoffset) { offset_ = newoffset; }
160
161 private:
162 const uint8_t * const buffer_;
163 const size_t length_;
164 size_t offset_;
165};
166
ksakamoto@chromium.org74343ba2013-05-08 01:20:29 +0000167// Round a value up to the nearest multiple of 4. Don't round the value in the
168// case that rounding up overflows.
169template<typename T> T Round4(T value) {
170 if (std::numeric_limits<T>::max() - value < 3) {
171 return value;
172 }
173 return (value + 3) & ~3;
174}
175
ksakamoto@chromium.orga416dc62013-05-08 03:39:15 +0000176template<typename T> T Round2(T value) {
177 if (value == std::numeric_limits<T>::max()) {
178 return value;
179 }
180 return (value + 1) & ~1;
181}
182
ksakamoto@chromium.org74343ba2013-05-08 01:20:29 +0000183bool IsValidVersionTag(uint32_t tag);
184
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000185#define FOR_EACH_TABLE_TYPE \
bashi@chromium.org6462c582014-06-27 06:24:49 +0000186 F(cbdt, CBDT) \
187 F(cblc, CBLC) \
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000188 F(cff, CFF) \
189 F(cmap, CMAP) \
190 F(cvt, CVT) \
191 F(fpgm, FPGM) \
192 F(gasp, GASP) \
bashi@google.com00b790a2011-01-27 06:35:42 +0000193 F(gdef, GDEF) \
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000194 F(glyf, GLYF) \
bashi@chromium.orgced71122011-02-17 10:23:47 +0000195 F(gpos, GPOS) \
bashi@chromium.orga5748662011-03-18 17:48:29 +0000196 F(gsub, GSUB) \
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000197 F(hdmx, HDMX) \
198 F(head, HEAD) \
199 F(hhea, HHEA) \
200 F(hmtx, HMTX) \
yusukes@chromium.orgf12575f2010-02-02 21:26:17 +0000201 F(kern, KERN) \
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000202 F(loca, LOCA) \
203 F(ltsh, LTSH) \
ksakamoto@chromium.orgeea48362014-01-20 02:15:37 +0000204 F(math, MATH) \
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000205 F(maxp, MAXP) \
206 F(name, NAME) \
207 F(os2, OS2) \
208 F(post, POST) \
209 F(prep, PREP) \
210 F(vdmx, VDMX) \
bashi@chromium.org4dcad602011-03-28 20:51:38 +0000211 F(vorg, VORG) \
212 F(vhea, VHEA) \
213 F(vmtx, VMTX)
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000214
215#define F(name, capname) struct OpenType##capname;
216FOR_EACH_TABLE_TYPE
217#undef F
218
219struct OpenTypeFile {
220 OpenTypeFile() {
221#define F(name, capname) name = NULL;
222 FOR_EACH_TABLE_TYPE
223#undef F
224 }
225
226 uint32_t version;
227 uint16_t num_tables;
228 uint16_t search_range;
229 uint16_t entry_selector;
230 uint16_t range_shift;
231
232#define F(name, capname) OpenType##capname *name;
233FOR_EACH_TABLE_TYPE
234#undef F
235};
236
bashi@chromium.org4dcad602011-03-28 20:51:38 +0000237#define F(name, capname) \
238bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \
239bool ots_##name##_should_serialise(OpenTypeFile *f); \
240bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \
241void ots_##name##_free(OpenTypeFile *f);
242// TODO(yusukes): change these function names to follow Chromium coding rule.
243FOR_EACH_TABLE_TYPE
244#undef F
245
yusukes@chromium.orgd257d182009-11-04 04:56:32 +0000246} // namespace ots
247
248#endif // OTS_H_