1d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Use of this source code is governed by a BSD-style license that can be
3d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// found in the LICENSE file.
4d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
5d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#ifndef OPENTYPE_SANITISER_H_
6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#define OPENTYPE_SANITISER_H_
7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
86a0c735027d75e13d03f286ffde9a696ee52d920agl@chromium.org#if defined(_WIN32)
998281afef95be7fee74edc8df7351f8b5e9969d1agl@chromium.org#include <stdlib.h>
10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef signed char int8_t;
11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef unsigned char uint8_t;
12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef short int16_t;
13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef unsigned short uint16_t;
14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef int int32_t;
15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef unsigned int uint32_t;
16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef __int64 int64_t;
17d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgtypedef unsigned __int64 uint64_t;
1898281afef95be7fee74edc8df7351f8b5e9969d1agl@chromium.org#define ntohl(x) _byteswap_ulong (x)
1998281afef95be7fee74edc8df7351f8b5e9969d1agl@chromium.org#define ntohs(x) _byteswap_ushort (x)
2098281afef95be7fee74edc8df7351f8b5e9969d1agl@chromium.org#define htonl(x) _byteswap_ulong (x)
2198281afef95be7fee74edc8df7351f8b5e9969d1agl@chromium.org#define htons(x) _byteswap_ushort (x)
22d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#else
23d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <arpa/inet.h>
24d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <stdint.h>
25d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#endif
26d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
27d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <algorithm>  // for std::min
28d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <cassert>
2918908189deb0ea39155f5558173862807e2936e1agl@chromium.org#include <cstddef>
30d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <cstring>
31d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
32d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgnamespace ots {
33d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
34d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// -----------------------------------------------------------------------------
35d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// This is an interface for an abstract stream class which is used for writing
36d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// the serialised results out.
37d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// -----------------------------------------------------------------------------
38d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgclass OTSStream {
39d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org public:
40d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  OTSStream() {
41d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    ResetChecksum();
42d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
43d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
44d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  virtual ~OTSStream() {}
45d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
46d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  // This should be implemented to perform the actual write.
47d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  virtual bool WriteRaw(const void *data, size_t length) = 0;
48d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
49d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool Write(const void *data, size_t length) {
50d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (!length) return false;
51d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
52d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    const size_t orig_length = length;
53d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    size_t offset = 0;
54d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (chksum_buffer_offset_) {
55d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      const size_t l =
56d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        std::min(length, static_cast<size_t>(4) - chksum_buffer_offset_);
57d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l);
58d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      chksum_buffer_offset_ += l;
59d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      offset += l;
60d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      length -= l;
61d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
62d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
63d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (chksum_buffer_offset_ == 4) {
6419a629d15a4f78d5d37cee6aabdb71f7d9400ca6yusukes@chromium.org      uint32_t chksum;
6519a629d15a4f78d5d37cee6aabdb71f7d9400ca6yusukes@chromium.org      std::memcpy(&chksum, chksum_buffer_, 4);
6619a629d15a4f78d5d37cee6aabdb71f7d9400ca6yusukes@chromium.org      chksum_ += ntohl(chksum);
67d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      chksum_buffer_offset_ = 0;
68d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
69d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
70d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    while (length >= 4) {
71d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      chksum_ += ntohl(*reinterpret_cast<const uint32_t*>(
72d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org          reinterpret_cast<const uint8_t*>(data) + offset));
73d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      length -= 4;
74d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      offset += 4;
75d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
76d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
77d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (length) {
78d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (chksum_buffer_offset_ != 0) return false;  // not reached
79d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (length > 4) return false;  // not reached
80d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      std::memcpy(chksum_buffer_,
81d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org             reinterpret_cast<const uint8_t*>(data) + offset, length);
82d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      chksum_buffer_offset_ = length;
83d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
84d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
85d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return WriteRaw(data, orig_length);
86d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
87d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
88d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  virtual bool Seek(off_t position) = 0;
89d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  virtual off_t Tell() const = 0;
90d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
91d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  virtual bool Pad(size_t bytes) {
92d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    static const uint32_t kZero = 0;
93d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    while (bytes >= 4) {
94d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!WriteTag(kZero)) return false;
95d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      bytes -= 4;
96d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
97d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    while (bytes) {
98d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      static const uint8_t kZerob = 0;
99d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!Write(&kZerob, 1)) return false;
100d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      bytes--;
101d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
102d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return true;
103d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
104d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
10593aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com  bool WriteU8(uint8_t v) {
10693aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com    return Write(&v, sizeof(v));
10793aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com  }
10893aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com
109d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteU16(uint16_t v) {
110d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    v = htons(v);
111d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
112d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
113d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
114d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteS16(int16_t v) {
115d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    v = htons(v);
116d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
117d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
118d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
11993aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com  bool WriteU24(uint32_t v) {
12093aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com    v = htonl(v);
12193aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com    return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
12293aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com  }
12393aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com
124d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteU32(uint32_t v) {
125d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    v = htonl(v);
126d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
127d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
128d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
129d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteS32(int32_t v) {
130d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    v = htonl(v);
131d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
132d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
133d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
134d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteR64(uint64_t v) {
135d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
136d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
137d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
138d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  bool WriteTag(uint32_t v) {
139d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return Write(&v, sizeof(v));
140d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
141d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
142d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  void ResetChecksum() {
143d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    chksum_ = 0;
144d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    chksum_buffer_offset_ = 0;
145d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
146d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
147d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  uint32_t chksum() const {
148d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    assert(chksum_buffer_offset_ == 0);
149d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return chksum_;
150d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
151d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
152d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  struct ChecksumState {
153d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    uint32_t chksum;
154d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    uint8_t chksum_buffer[4];
155d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    unsigned chksum_buffer_offset;
156d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  };
157d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
158d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  ChecksumState SaveChecksumState() const {
159d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    ChecksumState s;
160d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    s.chksum = chksum_;
161d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    s.chksum_buffer_offset = chksum_buffer_offset_;
162d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    std::memcpy(s.chksum_buffer, chksum_buffer_, 4);
163d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
164d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return s;
165d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
166d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
167d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  void RestoreChecksum(const ChecksumState &s) {
168d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    assert(chksum_buffer_offset_ == 0);
169d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    chksum_ += s.chksum;
170d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    chksum_buffer_offset_ = s.chksum_buffer_offset;
171d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    std::memcpy(chksum_buffer_, s.chksum_buffer, 4);
172d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
173d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
174d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org protected:
175d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  uint32_t chksum_;
176d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  uint8_t chksum_buffer_[4];
177d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  unsigned chksum_buffer_offset_;
178d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org};
179d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
180d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// -----------------------------------------------------------------------------
181d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Process a given OpenType file and write out a sanitised version
182d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org//   output: a pointer to an object implementing the OTSStream interface. The
183d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org//     sanitisied output will be written to this. In the even of a failure,
184d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org//     partial output may have been written.
185d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org//   input: the OpenType file
186d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org//   length: the size, in bytes, of |input|
187d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// -----------------------------------------------------------------------------
188d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool Process(OTSStream *output, const uint8_t *input, size_t length);
189d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
190d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Force to disable debug output even when the library is compiled with
191d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// -DOTS_DEBUG.
192d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgvoid DisableDebugOutput();
193d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
19474343ba7bd420519a9a4f7b22977d7771286f6f8ksakamoto@chromium.org// Enable WOFF2 support(experimental).
1956462c58fa123bb89baf1ec4b7538d8f2c682dc8bbashi@chromium.org// TODO(bashi): Remove WOFF2 from OTS.
19674343ba7bd420519a9a4f7b22977d7771286f6f8ksakamoto@chromium.orgvoid EnableWOFF2();
19774343ba7bd420519a9a4f7b22977d7771286f6f8ksakamoto@chromium.org
1986462c58fa123bb89baf1ec4b7538d8f2c682dc8bbashi@chromium.org// Force to disable dropping CBDT/CBLC tables.
1996462c58fa123bb89baf1ec4b7538d8f2c682dc8bbashi@chromium.orgvoid DoNotDropColorBitmapTables();
2006462c58fa123bb89baf1ec4b7538d8f2c682dc8bbashi@chromium.org
201d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}  // namespace ots
202d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
203d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#endif  // OPENTYPE_SANITISER_H_
204