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
19template <typename T, size_t N>
20char (&ArraySizeHelper(T (&array)[N]))[N];
21#define arraysize(array) (sizeof(ArraySizeHelper(array)))
22
23namespace 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
112  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
123  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
155  const uint8_t *buffer() const { return buffer_; }
156  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
167// 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
176template<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
183bool IsValidVersionTag(uint32_t tag);
184
185#define FOR_EACH_TABLE_TYPE \
186  F(cbdt, CBDT) \
187  F(cblc, CBLC) \
188  F(cff, CFF) \
189  F(cmap, CMAP) \
190  F(cvt, CVT) \
191  F(fpgm, FPGM) \
192  F(gasp, GASP) \
193  F(gdef, GDEF) \
194  F(glyf, GLYF) \
195  F(gpos, GPOS) \
196  F(gsub, GSUB) \
197  F(hdmx, HDMX) \
198  F(head, HEAD) \
199  F(hhea, HHEA) \
200  F(hmtx, HMTX) \
201  F(kern, KERN) \
202  F(loca, LOCA) \
203  F(ltsh, LTSH) \
204  F(math, MATH) \
205  F(maxp, MAXP) \
206  F(name, NAME) \
207  F(os2, OS2) \
208  F(post, POST) \
209  F(prep, PREP) \
210  F(vdmx, VDMX) \
211  F(vorg, VORG) \
212  F(vhea, VHEA) \
213  F(vmtx, VMTX)
214
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
237#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
246}  // namespace ots
247
248#endif  // OTS_H_
249