| Index: third_party/ots/src/ots.h
|
| diff --git a/third_party/ots/src/ots.h b/third_party/ots/src/ots.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ba3ba77a286cf3ad57bcee654689d01ebec4d74a
|
| --- /dev/null
|
| +++ b/third_party/ots/src/ots.h
|
| @@ -0,0 +1,259 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef OTS_H_
|
| +#define OTS_H_
|
| +
|
| +#include <stddef.h>
|
| +#include <cstdarg>
|
| +#include <cstddef>
|
| +#include <cstdio>
|
| +#include <cstdlib>
|
| +#include <cstring>
|
| +#include <limits>
|
| +
|
| +#include "opentype-sanitiser.h"
|
| +
|
| +// arraysize borrowed from base/basictypes.h
|
| +template <typename T, size_t N>
|
| +char (&ArraySizeHelper(T (&array)[N]))[N];
|
| +#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
| +
|
| +namespace ots {
|
| +
|
| +#if !defined(OTS_DEBUG)
|
| +#define OTS_FAILURE() false
|
| +#else
|
| +#define OTS_FAILURE() \
|
| + (\
|
| + std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \
|
| + __FILE__, __LINE__, __FUNCTION__) \
|
| + && false\
|
| + )
|
| +#endif
|
| +
|
| +// All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the original
|
| +// message-less OTS_FAILURE(), so that the current parser will return 'false' as
|
| +// its result (indicating a failure).
|
| +
|
| +#if !defined(OTS_DEBUG)
|
| +#define OTS_MESSAGE_(level,otf_,...) \
|
| + (otf_)->context->Message(level,__VA_ARGS__)
|
| +#else
|
| +#define OTS_MESSAGE_(level,otf_,...) \
|
| + OTS_FAILURE(), \
|
| + (otf_)->context->Message(level,__VA_ARGS__)
|
| +#endif
|
| +
|
| +// Generate a simple message
|
| +#define OTS_FAILURE_MSG_(otf_,...) \
|
| + (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false)
|
| +
|
| +#define OTS_WARNING_MSG_(otf_,...) \
|
| + OTS_MESSAGE_(1,otf_,__VA_ARGS__)
|
| +
|
| +// Generate a message with an associated table tag
|
| +#define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
|
| + (OTS_MESSAGE_(0,otf_,"%4.4s: %s", tag_, msg_), false)
|
| +
|
| +// Convenience macros for use in files that only handle a single table tag,
|
| +// defined as TABLE_NAME at the top of the file; the 'file' variable is
|
| +// expected to be the current OpenTypeFile pointer.
|
| +#define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
|
| +
|
| +#define OTS_WARNING(...) OTS_WARNING_MSG_(file, TABLE_NAME ": " __VA_ARGS__)
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// Buffer helper class
|
| +//
|
| +// This class perform some trival buffer operations while checking for
|
| +// out-of-bounds errors. As a family they return false if anything is amiss,
|
| +// updating the current offset otherwise.
|
| +// -----------------------------------------------------------------------------
|
| +class Buffer {
|
| + public:
|
| + Buffer(const uint8_t *buf, size_t len)
|
| + : buffer_(buf),
|
| + length_(len),
|
| + offset_(0) { }
|
| +
|
| + bool Skip(size_t n_bytes) {
|
| + return Read(NULL, n_bytes);
|
| + }
|
| +
|
| + bool Read(uint8_t *buf, size_t n_bytes) {
|
| + if (n_bytes > 1024 * 1024 * 1024) {
|
| + return OTS_FAILURE();
|
| + }
|
| + if ((offset_ + n_bytes > length_) ||
|
| + (offset_ > length_ - n_bytes)) {
|
| + return OTS_FAILURE();
|
| + }
|
| + if (buf) {
|
| + std::memcpy(buf, buffer_ + offset_, n_bytes);
|
| + }
|
| + offset_ += n_bytes;
|
| + return true;
|
| + }
|
| +
|
| + inline bool ReadU8(uint8_t *value) {
|
| + if (offset_ + 1 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + *value = buffer_[offset_];
|
| + ++offset_;
|
| + return true;
|
| + }
|
| +
|
| + bool ReadU16(uint16_t *value) {
|
| + if (offset_ + 2 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
|
| + *value = ntohs(*value);
|
| + offset_ += 2;
|
| + return true;
|
| + }
|
| +
|
| + bool ReadS16(int16_t *value) {
|
| + return ReadU16(reinterpret_cast<uint16_t*>(value));
|
| + }
|
| +
|
| + bool ReadU24(uint32_t *value) {
|
| + if (offset_ + 3 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
|
| + static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
|
| + static_cast<uint32_t>(buffer_[offset_ + 2]);
|
| + offset_ += 3;
|
| + return true;
|
| + }
|
| +
|
| + bool ReadU32(uint32_t *value) {
|
| + if (offset_ + 4 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
|
| + *value = ntohl(*value);
|
| + offset_ += 4;
|
| + return true;
|
| + }
|
| +
|
| + bool ReadS32(int32_t *value) {
|
| + return ReadU32(reinterpret_cast<uint32_t*>(value));
|
| + }
|
| +
|
| + bool ReadTag(uint32_t *value) {
|
| + if (offset_ + 4 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
|
| + offset_ += 4;
|
| + return true;
|
| + }
|
| +
|
| + bool ReadR64(uint64_t *value) {
|
| + if (offset_ + 8 > length_) {
|
| + return OTS_FAILURE();
|
| + }
|
| + std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
|
| + offset_ += 8;
|
| + return true;
|
| + }
|
| +
|
| + const uint8_t *buffer() const { return buffer_; }
|
| + size_t offset() const { return offset_; }
|
| + size_t length() const { return length_; }
|
| +
|
| + void set_offset(size_t newoffset) { offset_ = newoffset; }
|
| +
|
| + private:
|
| + const uint8_t * const buffer_;
|
| + const size_t length_;
|
| + size_t offset_;
|
| +};
|
| +
|
| +// Round a value up to the nearest multiple of 4. Don't round the value in the
|
| +// case that rounding up overflows.
|
| +template<typename T> T Round4(T value) {
|
| + if (std::numeric_limits<T>::max() - value < 3) {
|
| + return value;
|
| + }
|
| + return (value + 3) & ~3;
|
| +}
|
| +
|
| +template<typename T> T Round2(T value) {
|
| + if (value == std::numeric_limits<T>::max()) {
|
| + return value;
|
| + }
|
| + return (value + 1) & ~1;
|
| +}
|
| +
|
| +bool IsValidVersionTag(uint32_t tag);
|
| +
|
| +#define FOR_EACH_TABLE_TYPE \
|
| + F(cff, CFF) \
|
| + F(cmap, CMAP) \
|
| + F(cvt, CVT) \
|
| + F(fpgm, FPGM) \
|
| + F(gasp, GASP) \
|
| + F(gdef, GDEF) \
|
| + F(glyf, GLYF) \
|
| + F(gpos, GPOS) \
|
| + F(gsub, GSUB) \
|
| + F(hdmx, HDMX) \
|
| + F(head, HEAD) \
|
| + F(hhea, HHEA) \
|
| + F(hmtx, HMTX) \
|
| + F(kern, KERN) \
|
| + F(loca, LOCA) \
|
| + F(ltsh, LTSH) \
|
| + F(math, MATH) \
|
| + F(maxp, MAXP) \
|
| + F(name, NAME) \
|
| + F(os2, OS2) \
|
| + F(post, POST) \
|
| + F(prep, PREP) \
|
| + F(vdmx, VDMX) \
|
| + F(vorg, VORG) \
|
| + F(vhea, VHEA) \
|
| + F(vmtx, VMTX)
|
| +
|
| +#define F(name, capname) struct OpenType##capname;
|
| +FOR_EACH_TABLE_TYPE
|
| +#undef F
|
| +
|
| +struct OpenTypeFile {
|
| + OpenTypeFile() {
|
| +#define F(name, capname) name = NULL;
|
| + FOR_EACH_TABLE_TYPE
|
| +#undef F
|
| + }
|
| +
|
| + uint32_t version;
|
| + uint16_t num_tables;
|
| + uint16_t search_range;
|
| + uint16_t entry_selector;
|
| + uint16_t range_shift;
|
| +
|
| + OTSContext *context;
|
| +
|
| +#define F(name, capname) OpenType##capname *name;
|
| +FOR_EACH_TABLE_TYPE
|
| +#undef F
|
| +};
|
| +
|
| +#define F(name, capname) \
|
| +bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \
|
| +bool ots_##name##_should_serialise(OpenTypeFile *f); \
|
| +bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \
|
| +void ots_##name##_free(OpenTypeFile *f);
|
| +// TODO(yusukes): change these function names to follow Chromium coding rule.
|
| +FOR_EACH_TABLE_TYPE
|
| +#undef F
|
| +
|
| +} // namespace ots
|
| +
|
| +#endif // OTS_H_
|
|
|