Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #ifndef OPENTYPE_SANITISER_H_ |
michael@0 | 6 | #define OPENTYPE_SANITISER_H_ |
michael@0 | 7 | |
michael@0 | 8 | #if defined(_WIN32) || defined(__CYGWIN__) |
michael@0 | 9 | #define OTS_DLL_IMPORT __declspec(dllimport) |
michael@0 | 10 | #define OTS_DLL_EXPORT __declspec(dllexport) |
michael@0 | 11 | #else |
michael@0 | 12 | #if __GNUC__ >= 4 |
michael@0 | 13 | #define OTS_DLL_IMPORT __attribute__((visibility ("default"))) |
michael@0 | 14 | #define OTS_DLL_EXPORT __attribute__((visibility ("default"))) |
michael@0 | 15 | #endif |
michael@0 | 16 | #endif |
michael@0 | 17 | |
michael@0 | 18 | #ifdef OTS_DLL |
michael@0 | 19 | #ifdef OTS_DLL_EXPORTS |
michael@0 | 20 | #define OTS_API OTS_DLL_EXPORT |
michael@0 | 21 | #else |
michael@0 | 22 | #define OTS_API OTS_DLL_IMPORT |
michael@0 | 23 | #endif |
michael@0 | 24 | #else |
michael@0 | 25 | #define OTS_API |
michael@0 | 26 | #endif |
michael@0 | 27 | |
michael@0 | 28 | #if defined(_WIN32) |
michael@0 | 29 | #include <stdlib.h> |
michael@0 | 30 | typedef signed char int8_t; |
michael@0 | 31 | typedef unsigned char uint8_t; |
michael@0 | 32 | typedef short int16_t; |
michael@0 | 33 | typedef unsigned short uint16_t; |
michael@0 | 34 | typedef int int32_t; |
michael@0 | 35 | typedef unsigned int uint32_t; |
michael@0 | 36 | typedef __int64 int64_t; |
michael@0 | 37 | typedef unsigned __int64 uint64_t; |
michael@0 | 38 | #define ntohl(x) _byteswap_ulong (x) |
michael@0 | 39 | #define ntohs(x) _byteswap_ushort (x) |
michael@0 | 40 | #define htonl(x) _byteswap_ulong (x) |
michael@0 | 41 | #define htons(x) _byteswap_ushort (x) |
michael@0 | 42 | #else |
michael@0 | 43 | #include <arpa/inet.h> |
michael@0 | 44 | #include <stdint.h> |
michael@0 | 45 | #endif |
michael@0 | 46 | |
michael@0 | 47 | #include <algorithm> |
michael@0 | 48 | #include <cassert> |
michael@0 | 49 | #include <cstddef> |
michael@0 | 50 | #include <cstring> |
michael@0 | 51 | |
michael@0 | 52 | namespace ots { |
michael@0 | 53 | |
michael@0 | 54 | // ----------------------------------------------------------------------------- |
michael@0 | 55 | // This is an interface for an abstract stream class which is used for writing |
michael@0 | 56 | // the serialised results out. |
michael@0 | 57 | // ----------------------------------------------------------------------------- |
michael@0 | 58 | class OTSStream { |
michael@0 | 59 | public: |
michael@0 | 60 | OTSStream() { |
michael@0 | 61 | ResetChecksum(); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | virtual ~OTSStream() {} |
michael@0 | 65 | |
michael@0 | 66 | // This should be implemented to perform the actual write. |
michael@0 | 67 | virtual bool WriteRaw(const void *data, size_t length) = 0; |
michael@0 | 68 | |
michael@0 | 69 | bool Write(const void *data, size_t length) { |
michael@0 | 70 | if (!length) return false; |
michael@0 | 71 | |
michael@0 | 72 | const size_t orig_length = length; |
michael@0 | 73 | size_t offset = 0; |
michael@0 | 74 | if (chksum_buffer_offset_) { |
michael@0 | 75 | const size_t l = |
michael@0 | 76 | std::min(length, static_cast<size_t>(4) - chksum_buffer_offset_); |
michael@0 | 77 | std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l); |
michael@0 | 78 | chksum_buffer_offset_ += l; |
michael@0 | 79 | offset += l; |
michael@0 | 80 | length -= l; |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | if (chksum_buffer_offset_ == 4) { |
michael@0 | 84 | uint32_t tmp; |
michael@0 | 85 | std::memcpy(&tmp, chksum_buffer_, 4); |
michael@0 | 86 | chksum_ += ntohl(tmp); |
michael@0 | 87 | chksum_buffer_offset_ = 0; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | while (length >= 4) { |
michael@0 | 91 | uint32_t tmp; |
michael@0 | 92 | std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset, |
michael@0 | 93 | sizeof(uint32_t)); |
michael@0 | 94 | chksum_ += ntohl(tmp); |
michael@0 | 95 | length -= 4; |
michael@0 | 96 | offset += 4; |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | if (length) { |
michael@0 | 100 | if (chksum_buffer_offset_ != 0) return false; // not reached |
michael@0 | 101 | if (length > 4) return false; // not reached |
michael@0 | 102 | std::memcpy(chksum_buffer_, |
michael@0 | 103 | reinterpret_cast<const uint8_t*>(data) + offset, length); |
michael@0 | 104 | chksum_buffer_offset_ = length; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | return WriteRaw(data, orig_length); |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | virtual bool Seek(off_t position) = 0; |
michael@0 | 111 | virtual off_t Tell() const = 0; |
michael@0 | 112 | |
michael@0 | 113 | virtual bool Pad(size_t bytes) { |
michael@0 | 114 | static const uint32_t kZero = 0; |
michael@0 | 115 | while (bytes >= 4) { |
michael@0 | 116 | if (!WriteTag(kZero)) return false; |
michael@0 | 117 | bytes -= 4; |
michael@0 | 118 | } |
michael@0 | 119 | while (bytes) { |
michael@0 | 120 | static const uint8_t kZerob = 0; |
michael@0 | 121 | if (!Write(&kZerob, 1)) return false; |
michael@0 | 122 | bytes--; |
michael@0 | 123 | } |
michael@0 | 124 | return true; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | bool WriteU8(uint8_t v) { |
michael@0 | 128 | return Write(&v, sizeof(v)); |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | bool WriteU16(uint16_t v) { |
michael@0 | 132 | v = htons(v); |
michael@0 | 133 | return Write(&v, sizeof(v)); |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | bool WriteS16(int16_t v) { |
michael@0 | 137 | v = htons(v); |
michael@0 | 138 | return Write(&v, sizeof(v)); |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | bool WriteU24(uint32_t v) { |
michael@0 | 142 | v = htonl(v); |
michael@0 | 143 | return Write(reinterpret_cast<uint8_t*>(&v)+1, 3); |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | bool WriteU32(uint32_t v) { |
michael@0 | 147 | v = htonl(v); |
michael@0 | 148 | return Write(&v, sizeof(v)); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | bool WriteS32(int32_t v) { |
michael@0 | 152 | v = htonl(v); |
michael@0 | 153 | return Write(&v, sizeof(v)); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | bool WriteR64(uint64_t v) { |
michael@0 | 157 | return Write(&v, sizeof(v)); |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | bool WriteTag(uint32_t v) { |
michael@0 | 161 | return Write(&v, sizeof(v)); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | void ResetChecksum() { |
michael@0 | 165 | chksum_ = 0; |
michael@0 | 166 | chksum_buffer_offset_ = 0; |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | uint32_t chksum() const { |
michael@0 | 170 | assert(chksum_buffer_offset_ == 0); |
michael@0 | 171 | return chksum_; |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | struct ChecksumState { |
michael@0 | 175 | uint32_t chksum; |
michael@0 | 176 | uint8_t chksum_buffer[4]; |
michael@0 | 177 | unsigned chksum_buffer_offset; |
michael@0 | 178 | }; |
michael@0 | 179 | |
michael@0 | 180 | ChecksumState SaveChecksumState() const { |
michael@0 | 181 | ChecksumState s; |
michael@0 | 182 | s.chksum = chksum_; |
michael@0 | 183 | s.chksum_buffer_offset = chksum_buffer_offset_; |
michael@0 | 184 | std::memcpy(s.chksum_buffer, chksum_buffer_, 4); |
michael@0 | 185 | |
michael@0 | 186 | return s; |
michael@0 | 187 | } |
michael@0 | 188 | |
michael@0 | 189 | void RestoreChecksum(const ChecksumState &s) { |
michael@0 | 190 | assert(chksum_buffer_offset_ == 0); |
michael@0 | 191 | chksum_ += s.chksum; |
michael@0 | 192 | chksum_buffer_offset_ = s.chksum_buffer_offset; |
michael@0 | 193 | std::memcpy(chksum_buffer_, s.chksum_buffer, 4); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | protected: |
michael@0 | 197 | uint32_t chksum_; |
michael@0 | 198 | uint8_t chksum_buffer_[4]; |
michael@0 | 199 | unsigned chksum_buffer_offset_; |
michael@0 | 200 | }; |
michael@0 | 201 | |
michael@0 | 202 | // ----------------------------------------------------------------------------- |
michael@0 | 203 | // Process a given OpenType file and write out a sanitised version |
michael@0 | 204 | // output: a pointer to an object implementing the OTSStream interface. The |
michael@0 | 205 | // sanitisied output will be written to this. In the even of a failure, |
michael@0 | 206 | // partial output may have been written. |
michael@0 | 207 | // input: the OpenType file |
michael@0 | 208 | // length: the size, in bytes, of |input| |
michael@0 | 209 | // ----------------------------------------------------------------------------- |
michael@0 | 210 | bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length); |
michael@0 | 211 | |
michael@0 | 212 | // Signature of the function to be provided by the client in order to report errors. |
michael@0 | 213 | // The return type is a boolean so that it can be used within an expression, |
michael@0 | 214 | // but the actual value is ignored. (Suggested convention is to always return 'false'.) |
michael@0 | 215 | #ifdef __GCC__ |
michael@0 | 216 | #define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3))) |
michael@0 | 217 | #else |
michael@0 | 218 | #define MSGFUNC_FMT_ATTR |
michael@0 | 219 | #endif |
michael@0 | 220 | typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR; |
michael@0 | 221 | |
michael@0 | 222 | // Set a callback function that will be called when OTS is reporting an error. |
michael@0 | 223 | void OTS_API SetMessageCallback(MessageFunc func, void *user_data); |
michael@0 | 224 | |
michael@0 | 225 | enum TableAction { |
michael@0 | 226 | TABLE_ACTION_DEFAULT, // Use OTS's default action for that table |
michael@0 | 227 | TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it |
michael@0 | 228 | TABLE_ACTION_PASSTHRU, // Serialize the table unchanged |
michael@0 | 229 | TABLE_ACTION_DROP // Drop the table |
michael@0 | 230 | }; |
michael@0 | 231 | |
michael@0 | 232 | // Signature of the function to be provided by the client to decide what action |
michael@0 | 233 | // to do for a given table. |
michael@0 | 234 | typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data); |
michael@0 | 235 | |
michael@0 | 236 | // Set a callback function that will be called when OTS needs to decide what to |
michael@0 | 237 | // do for a font table. |
michael@0 | 238 | void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data); |
michael@0 | 239 | |
michael@0 | 240 | // Force to disable debug output even when the library is compiled with |
michael@0 | 241 | // -DOTS_DEBUG. |
michael@0 | 242 | void DisableDebugOutput(); |
michael@0 | 243 | |
michael@0 | 244 | #ifdef MOZ_OTS_WOFF2 |
michael@0 | 245 | // Enable WOFF2 support(experimental). |
michael@0 | 246 | void EnableWOFF2(); |
michael@0 | 247 | #endif |
michael@0 | 248 | |
michael@0 | 249 | } // namespace ots |
michael@0 | 250 | |
michael@0 | 251 | #endif // OPENTYPE_SANITISER_H_ |