michael@0: // Copyright (c) 2009 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef OPENTYPE_SANITISER_H_ michael@0: #define OPENTYPE_SANITISER_H_ michael@0: michael@0: #if defined(_WIN32) || defined(__CYGWIN__) michael@0: #define OTS_DLL_IMPORT __declspec(dllimport) michael@0: #define OTS_DLL_EXPORT __declspec(dllexport) michael@0: #else michael@0: #if __GNUC__ >= 4 michael@0: #define OTS_DLL_IMPORT __attribute__((visibility ("default"))) michael@0: #define OTS_DLL_EXPORT __attribute__((visibility ("default"))) michael@0: #endif michael@0: #endif michael@0: michael@0: #ifdef OTS_DLL michael@0: #ifdef OTS_DLL_EXPORTS michael@0: #define OTS_API OTS_DLL_EXPORT michael@0: #else michael@0: #define OTS_API OTS_DLL_IMPORT michael@0: #endif michael@0: #else michael@0: #define OTS_API michael@0: #endif michael@0: michael@0: #if defined(_WIN32) michael@0: #include michael@0: typedef signed char int8_t; michael@0: typedef unsigned char uint8_t; michael@0: typedef short int16_t; michael@0: typedef unsigned short uint16_t; michael@0: typedef int int32_t; michael@0: typedef unsigned int uint32_t; michael@0: typedef __int64 int64_t; michael@0: typedef unsigned __int64 uint64_t; michael@0: #define ntohl(x) _byteswap_ulong (x) michael@0: #define ntohs(x) _byteswap_ushort (x) michael@0: #define htonl(x) _byteswap_ulong (x) michael@0: #define htons(x) _byteswap_ushort (x) michael@0: #else michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: namespace ots { michael@0: michael@0: // ----------------------------------------------------------------------------- michael@0: // This is an interface for an abstract stream class which is used for writing michael@0: // the serialised results out. michael@0: // ----------------------------------------------------------------------------- michael@0: class OTSStream { michael@0: public: michael@0: OTSStream() { michael@0: ResetChecksum(); michael@0: } michael@0: michael@0: virtual ~OTSStream() {} michael@0: michael@0: // This should be implemented to perform the actual write. michael@0: virtual bool WriteRaw(const void *data, size_t length) = 0; michael@0: michael@0: bool Write(const void *data, size_t length) { michael@0: if (!length) return false; michael@0: michael@0: const size_t orig_length = length; michael@0: size_t offset = 0; michael@0: if (chksum_buffer_offset_) { michael@0: const size_t l = michael@0: std::min(length, static_cast(4) - chksum_buffer_offset_); michael@0: std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l); michael@0: chksum_buffer_offset_ += l; michael@0: offset += l; michael@0: length -= l; michael@0: } michael@0: michael@0: if (chksum_buffer_offset_ == 4) { michael@0: uint32_t tmp; michael@0: std::memcpy(&tmp, chksum_buffer_, 4); michael@0: chksum_ += ntohl(tmp); michael@0: chksum_buffer_offset_ = 0; michael@0: } michael@0: michael@0: while (length >= 4) { michael@0: uint32_t tmp; michael@0: std::memcpy(&tmp, reinterpret_cast(data) + offset, michael@0: sizeof(uint32_t)); michael@0: chksum_ += ntohl(tmp); michael@0: length -= 4; michael@0: offset += 4; michael@0: } michael@0: michael@0: if (length) { michael@0: if (chksum_buffer_offset_ != 0) return false; // not reached michael@0: if (length > 4) return false; // not reached michael@0: std::memcpy(chksum_buffer_, michael@0: reinterpret_cast(data) + offset, length); michael@0: chksum_buffer_offset_ = length; michael@0: } michael@0: michael@0: return WriteRaw(data, orig_length); michael@0: } michael@0: michael@0: virtual bool Seek(off_t position) = 0; michael@0: virtual off_t Tell() const = 0; michael@0: michael@0: virtual bool Pad(size_t bytes) { michael@0: static const uint32_t kZero = 0; michael@0: while (bytes >= 4) { michael@0: if (!WriteTag(kZero)) return false; michael@0: bytes -= 4; michael@0: } michael@0: while (bytes) { michael@0: static const uint8_t kZerob = 0; michael@0: if (!Write(&kZerob, 1)) return false; michael@0: bytes--; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool WriteU8(uint8_t v) { michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteU16(uint16_t v) { michael@0: v = htons(v); michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteS16(int16_t v) { michael@0: v = htons(v); michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteU24(uint32_t v) { michael@0: v = htonl(v); michael@0: return Write(reinterpret_cast(&v)+1, 3); michael@0: } michael@0: michael@0: bool WriteU32(uint32_t v) { michael@0: v = htonl(v); michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteS32(int32_t v) { michael@0: v = htonl(v); michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteR64(uint64_t v) { michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: bool WriteTag(uint32_t v) { michael@0: return Write(&v, sizeof(v)); michael@0: } michael@0: michael@0: void ResetChecksum() { michael@0: chksum_ = 0; michael@0: chksum_buffer_offset_ = 0; michael@0: } michael@0: michael@0: uint32_t chksum() const { michael@0: assert(chksum_buffer_offset_ == 0); michael@0: return chksum_; michael@0: } michael@0: michael@0: struct ChecksumState { michael@0: uint32_t chksum; michael@0: uint8_t chksum_buffer[4]; michael@0: unsigned chksum_buffer_offset; michael@0: }; michael@0: michael@0: ChecksumState SaveChecksumState() const { michael@0: ChecksumState s; michael@0: s.chksum = chksum_; michael@0: s.chksum_buffer_offset = chksum_buffer_offset_; michael@0: std::memcpy(s.chksum_buffer, chksum_buffer_, 4); michael@0: michael@0: return s; michael@0: } michael@0: michael@0: void RestoreChecksum(const ChecksumState &s) { michael@0: assert(chksum_buffer_offset_ == 0); michael@0: chksum_ += s.chksum; michael@0: chksum_buffer_offset_ = s.chksum_buffer_offset; michael@0: std::memcpy(chksum_buffer_, s.chksum_buffer, 4); michael@0: } michael@0: michael@0: protected: michael@0: uint32_t chksum_; michael@0: uint8_t chksum_buffer_[4]; michael@0: unsigned chksum_buffer_offset_; michael@0: }; michael@0: michael@0: // ----------------------------------------------------------------------------- michael@0: // Process a given OpenType file and write out a sanitised version michael@0: // output: a pointer to an object implementing the OTSStream interface. The michael@0: // sanitisied output will be written to this. In the even of a failure, michael@0: // partial output may have been written. michael@0: // input: the OpenType file michael@0: // length: the size, in bytes, of |input| michael@0: // ----------------------------------------------------------------------------- michael@0: bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length); michael@0: michael@0: // Signature of the function to be provided by the client in order to report errors. michael@0: // The return type is a boolean so that it can be used within an expression, michael@0: // but the actual value is ignored. (Suggested convention is to always return 'false'.) michael@0: #ifdef __GCC__ michael@0: #define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3))) michael@0: #else michael@0: #define MSGFUNC_FMT_ATTR michael@0: #endif michael@0: typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR; michael@0: michael@0: // Set a callback function that will be called when OTS is reporting an error. michael@0: void OTS_API SetMessageCallback(MessageFunc func, void *user_data); michael@0: michael@0: enum TableAction { michael@0: TABLE_ACTION_DEFAULT, // Use OTS's default action for that table michael@0: TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it michael@0: TABLE_ACTION_PASSTHRU, // Serialize the table unchanged michael@0: TABLE_ACTION_DROP // Drop the table michael@0: }; michael@0: michael@0: // Signature of the function to be provided by the client to decide what action michael@0: // to do for a given table. michael@0: typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data); michael@0: michael@0: // Set a callback function that will be called when OTS needs to decide what to michael@0: // do for a font table. michael@0: void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data); michael@0: michael@0: // Force to disable debug output even when the library is compiled with michael@0: // -DOTS_DEBUG. michael@0: void DisableDebugOutput(); michael@0: michael@0: #ifdef MOZ_OTS_WOFF2 michael@0: // Enable WOFF2 support(experimental). michael@0: void EnableWOFF2(); michael@0: #endif michael@0: michael@0: } // namespace ots michael@0: michael@0: #endif // OPENTYPE_SANITISER_H_