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 // 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) 51 const bool g_transcode_hints = false; 52 #else 53 const 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 // ----------------------------------------------------------------------------- 63 class 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. 169 template<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 176 template<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 183 bool IsValidVersionTag(uint32_t tag); 184 185 #define FOR_EACH_TABLE_TYPE \ 186 F(cff, CFF) \ 187 F(cmap, CMAP) \ 188 F(cvt, CVT) \ 189 F(fpgm, FPGM) \ 190 F(gasp, GASP) \ 191 F(gdef, GDEF) \ 192 F(glyf, GLYF) \ 193 F(gpos, GPOS) \ 194 F(gsub, GSUB) \ 195 F(hdmx, HDMX) \ 196 F(head, HEAD) \ 197 F(hhea, HHEA) \ 198 F(hmtx, HMTX) \ 199 F(kern, KERN) \ 200 F(loca, LOCA) \ 201 F(ltsh, LTSH) \ 202 F(maxp, MAXP) \ 203 F(name, NAME) \ 204 F(os2, OS2) \ 205 F(post, POST) \ 206 F(prep, PREP) \ 207 F(vdmx, VDMX) \ 208 F(vorg, VORG) \ 209 F(vhea, VHEA) \ 210 F(vmtx, VMTX) 211 212 #define F(name, capname) struct OpenType##capname; 213 FOR_EACH_TABLE_TYPE 214 #undef F 215 216 struct OpenTypeFile { 217 OpenTypeFile() { 218 #define F(name, capname) name = NULL; 219 FOR_EACH_TABLE_TYPE 220 #undef F 221 } 222 223 uint32_t version; 224 uint16_t num_tables; 225 uint16_t search_range; 226 uint16_t entry_selector; 227 uint16_t range_shift; 228 229 #define F(name, capname) OpenType##capname *name; 230 FOR_EACH_TABLE_TYPE 231 #undef F 232 }; 233 234 #define F(name, capname) \ 235 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \ 236 bool ots_##name##_should_serialise(OpenTypeFile *f); \ 237 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \ 238 void ots_##name##_free(OpenTypeFile *f); 239 // TODO(yusukes): change these function names to follow Chromium coding rule. 240 FOR_EACH_TABLE_TYPE 241 #undef F 242 243 } // namespace ots 244 245 #endif // OTS_H_ 246