Home | History | Annotate | Download | only in src
      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