Commit efffce8e authored by Dominik Röttsches's avatar Dominik Röttsches Committed by Chromium LUCI CQ

Move OTS to a DEPS based checkout

Instead of keeping a local copy, move OTS to an external checkout. This
allows easier tracking of changes and easier rolling of OTS into
Chromium.

Keep OTS at e5d1029ad9a16e1209b2fe7a2f8901aa42a9698c in this CL, which
points to [1] which is equivalent to the copy of the source code that
we used before. Roll OTS to tip of tree in a forthcoming commit.

[1] https://chromium.googlesource.com/external/github.com/khaledhosny/ots/+log/refs/heads/chromiumOTSbeforeDEPS

Bug: 1158389
Change-Id: If8fe76792b171cf0df1366b820db6d6291baf36b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589853
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844507}
parent ffec5f4d
...@@ -264,6 +264,10 @@ vars = { ...@@ -264,6 +264,10 @@ vars = {
# and whatever else without interference from each other. # and whatever else without interference from each other.
'emoji_segmenter_revision': '9ba6d25d0d9313569665d4a9d2b34f0f39f9a50e', 'emoji_segmenter_revision': '9ba6d25d0d9313569665d4a9d2b34f0f39f9a50e',
# Three lines of non-changing comments so that # Three lines of non-changing comments so that
# the commit queue can handle CLs rolling OTS
# and whatever else without interference from each other.
'ots_revision': 'e5d1029ad9a16e1209b2fe7a2f8901aa42a9698c',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling catapult # the commit queue can handle CLs rolling catapult
# and whatever else without interference from each other. # and whatever else without interference from each other.
'catapult_revision': 'cf567b6b961687e00cdc2ded7bcb4fc72379fa59', 'catapult_revision': 'cf567b6b961687e00cdc2ded7bcb4fc72379fa59',
...@@ -960,6 +964,9 @@ deps = { ...@@ -960,6 +964,9 @@ deps = {
'src/third_party/emoji-segmenter/src': 'src/third_party/emoji-segmenter/src':
Var('chromium_git') + '/external/github.com/google/emoji-segmenter.git' + '@' + Var('emoji_segmenter_revision'), Var('chromium_git') + '/external/github.com/google/emoji-segmenter.git' + '@' + Var('emoji_segmenter_revision'),
'src/third_party/ots/src':
Var('chromium_git') + '/external/github.com/khaledhosny/ots.git' + '@' + Var('ots_revision'),
'src/third_party/libgav1/src': 'src/third_party/libgav1/src':
Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'a5ee0e00923c355ef3aad2b2829365a9fde84430', Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'a5ee0e00923c355ef3aad2b2829365a9fde84430',
......
...@@ -180,6 +180,7 @@ ...@@ -180,6 +180,7 @@
/openh264/src /openh264/src
/openscreen/src /openscreen/src
/openxr/src /openxr/src
/ots/src
/pdfsqueeze /pdfsqueeze
/pdfium /pdfium
/pefile /pefile
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h" #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/ots/include/ots-memory-stream.h" #include "third_party/ots/src/include/ots-memory-stream.h"
#include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkStream.h"
#include <hb.h> #include <hb.h>
......
...@@ -5,73 +5,73 @@ ...@@ -5,73 +5,73 @@
import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/libfuzzer/fuzzer_test.gni")
config("ots_config") { config("ots_config") {
include_dirs = [ "include" ] include_dirs = [ "src/include" ]
} }
static_library("ots") { static_library("ots") {
sources = [ sources = [
"include/opentype-sanitiser.h", "src/include/opentype-sanitiser.h",
"include/ots-memory-stream.h", "src/include/ots-memory-stream.h",
"src/cff.cc", "src/src/cff.cc",
"src/cff.h", "src/src/cff.h",
"src/cff_type2_charstring.cc", "src/src/cff_type2_charstring.cc",
"src/cff_type2_charstring.h", "src/src/cff_type2_charstring.h",
"src/cmap.cc", "src/src/cmap.cc",
"src/cmap.h", "src/src/cmap.h",
"src/cvt.cc", "src/src/cvt.cc",
"src/cvt.h", "src/src/cvt.h",
"src/fpgm.cc", "src/src/fpgm.cc",
"src/fpgm.h", "src/src/fpgm.h",
"src/gasp.cc", "src/src/gasp.cc",
"src/gasp.h", "src/src/gasp.h",
"src/gdef.cc", "src/src/gdef.cc",
"src/gdef.h", "src/src/gdef.h",
"src/glyf.cc", "src/src/glyf.cc",
"src/glyf.h", "src/src/glyf.h",
"src/gpos.cc", "src/src/gpos.cc",
"src/gpos.h", "src/src/gpos.h",
"src/gsub.cc", "src/src/gsub.cc",
"src/gsub.h", "src/src/gsub.h",
"src/hdmx.cc", "src/src/hdmx.cc",
"src/hdmx.h", "src/src/hdmx.h",
"src/head.cc", "src/src/head.cc",
"src/head.h", "src/src/head.h",
"src/hhea.cc", "src/src/hhea.cc",
"src/hhea.h", "src/src/hhea.h",
"src/hmtx.cc", "src/src/hmtx.cc",
"src/hmtx.h", "src/src/hmtx.h",
"src/kern.cc", "src/src/kern.cc",
"src/kern.h", "src/src/kern.h",
"src/layout.cc", "src/src/layout.cc",
"src/layout.h", "src/src/layout.h",
"src/loca.cc", "src/src/loca.cc",
"src/loca.h", "src/src/loca.h",
"src/ltsh.cc", "src/src/ltsh.cc",
"src/ltsh.h", "src/src/ltsh.h",
"src/math.cc", "src/src/math.cc",
"src/math_.h", "src/src/math_.h",
"src/maxp.cc", "src/src/maxp.cc",
"src/maxp.h", "src/src/maxp.h",
"src/metrics.cc", "src/src/metrics.cc",
"src/metrics.h", "src/src/metrics.h",
"src/name.cc", "src/src/name.cc",
"src/name.h", "src/src/name.h",
"src/os2.cc", "src/src/os2.cc",
"src/os2.h", "src/src/os2.h",
"src/ots.cc", "src/src/ots.cc",
"src/ots.h", "src/src/ots.h",
"src/post.cc", "src/src/post.cc",
"src/post.h", "src/src/post.h",
"src/prep.cc", "src/src/prep.cc",
"src/prep.h", "src/src/prep.h",
"src/vdmx.cc", "src/src/vdmx.cc",
"src/vdmx.h", "src/src/vdmx.h",
"src/vhea.cc", "src/src/vhea.cc",
"src/vhea.h", "src/src/vhea.h",
"src/vmtx.cc", "src/src/vmtx.cc",
"src/vmtx.h", "src/src/vmtx.h",
"src/vorg.cc", "src/src/vorg.cc",
"src/vorg.h", "src/src/vorg.h",
] ]
public_configs = [ ":ots_config" ] public_configs = [ ":ots_config" ]
......
Name: OTS (OpenType Sanitizer) Name: OTS (OpenType Sanitizer)
URL: https://github.com/khaledhosny/ots.git URL: https://github.com/khaledhosny/ots.git
Version: fbe8db1e192958055fef1607ae69b478789ba22a Version: e5d1029ad9a16e1209b2fe7a2f8901aa42a9698c
Security Critical: yes Security Critical: yes
License: BSD License: BSD
Local Modifications: Local Modifications:
- This only includes src/ and include/ directories, and the files under the
repository root. Unneeded direcories such as tests/, util/ are removed.
- src/ots.cc: Changed include path to woff2_dec.h.
- BUILD.gn: Added. - BUILD.gn: Added.
- fuzz/: Added. - fuzz/: Added.
- ots.cc: Allow CFF2 outlines, upstreamed in - e5d1029ad9a16e1209b2fe7a2f8901aa42a9698c points to a commit
https://github.com/khaledhosny/ots/pull/161 chromiumOTSbeforeDEPS which has additional changes backported to the ots
- glyf.h, glyf.cc - Backport of "Sanitise values for fonts with invalid version at which we switched to a DEPS based checkout, these changes are:
maxPoints and maxComponentPoints" - e5d1029 [glyf] Guard access to maxp version 1 fields
https://github.com/khaledhosny/ots/pull/227 - 177b26f ComponentPointCount initialisation review comments
- glyf.cc - Backport of "[glyf] Guard access to maxp version 1 field" - b8138ac Factor out glyph buffer retrieval
Upstream commit 1141c81c411b599e40496679129d0884715e8650 - 9b14724 Sanitise values for maxPoints, maxComponentPoints maxComponentDepth
- aeb6ce9 Don't bail if CFF2 glyph table is present
\ No newline at end of file
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "third_party/ots/include/opentype-sanitiser.h" #include "third_party/ots/src/include/opentype-sanitiser.h"
#include "third_party/ots/include/ots-memory-stream.h" #include "third_party/ots/src/include/ots-memory-stream.h"
static uint8_t buffer[256 * 1024] = { 0 }; static uint8_t buffer[256 * 1024] = { 0 };
......
// Copyright (c) 2009-2017 The OTS 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 OPENTYPE_SANITISER_H_
#define OPENTYPE_SANITISER_H_
#if defined(_WIN32)
#include <stdlib.h>
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define ots_ntohl(x) _byteswap_ulong (x)
#define ots_ntohs(x) _byteswap_ushort (x)
#define ots_htonl(x) _byteswap_ulong (x)
#define ots_htons(x) _byteswap_ushort (x)
#else
#include <arpa/inet.h>
#include <stdint.h>
#define ots_ntohl(x) ntohl (x)
#define ots_ntohs(x) ntohs (x)
#define ots_htonl(x) htonl (x)
#define ots_htons(x) htons (x)
#endif
#include <sys/types.h>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#define OTS_TAG(c1,c2,c3,c4) ((uint32_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
#define OTS_UNTAG(tag) ((char)((tag)>>24)), ((char)((tag)>>16)), ((char)((tag)>>8)), ((char)(tag))
namespace ots {
// -----------------------------------------------------------------------------
// This is an interface for an abstract stream class which is used for writing
// the serialised results out.
// -----------------------------------------------------------------------------
class OTSStream {
public:
OTSStream() : chksum_(0) {}
virtual ~OTSStream() {}
// This should be implemented to perform the actual write.
virtual bool WriteRaw(const void *data, size_t length) = 0;
bool Write(const void *data, size_t length) {
if (!length) return false;
const size_t orig_length = length;
size_t offset = 0;
size_t chksum_offset = Tell() & 3;
if (chksum_offset) {
const size_t l = std::min(length, static_cast<size_t>(4) - chksum_offset);
uint32_t tmp = 0;
std::memcpy(reinterpret_cast<uint8_t *>(&tmp) + chksum_offset, data, l);
chksum_ += ots_ntohl(tmp);
length -= l;
offset += l;
}
while (length >= 4) {
uint32_t tmp;
std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
sizeof(uint32_t));
chksum_ += ots_ntohl(tmp);
length -= 4;
offset += 4;
}
if (length) {
if (length > 4) return false; // not reached
uint32_t tmp = 0;
std::memcpy(&tmp,
reinterpret_cast<const uint8_t*>(data) + offset, length);
chksum_ += ots_ntohl(tmp);
}
return WriteRaw(data, orig_length);
}
virtual bool Seek(off_t position) = 0;
virtual off_t Tell() const = 0;
virtual bool Pad(size_t bytes) {
static const uint32_t kZero = 0;
while (bytes >= 4) {
if (!Write(&kZero, 4)) return false;
bytes -= 4;
}
while (bytes) {
static const uint8_t kZerob = 0;
if (!Write(&kZerob, 1)) return false;
bytes--;
}
return true;
}
bool WriteU8(uint8_t v) {
return Write(&v, sizeof(v));
}
bool WriteU16(uint16_t v) {
v = ots_htons(v);
return Write(&v, sizeof(v));
}
bool WriteS16(int16_t v) {
v = ots_htons(v);
return Write(&v, sizeof(v));
}
bool WriteU24(uint32_t v) {
v = ots_htonl(v);
return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
}
bool WriteU32(uint32_t v) {
v = ots_htonl(v);
return Write(&v, sizeof(v));
}
bool WriteS32(int32_t v) {
v = ots_htonl(v);
return Write(&v, sizeof(v));
}
bool WriteR64(uint64_t v) {
return Write(&v, sizeof(v));
}
void ResetChecksum() {
assert((Tell() & 3) == 0);
chksum_ = 0;
}
uint32_t chksum() const {
return chksum_;
}
protected:
uint32_t chksum_;
};
#ifdef __GCC__
#define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
#else
#define MSGFUNC_FMT_ATTR
#endif
enum TableAction {
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially dropping it
TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
TABLE_ACTION_DROP // Drop the table
};
class OTSContext {
public:
OTSContext() {}
virtual ~OTSContext() {}
// Process a given OpenType file and write out a sanitized version
// output: a pointer to an object implementing the OTSStream interface. The
// sanitisied output will be written to this. In the even of a failure,
// partial output may have been written.
// input: the OpenType file
// length: the size, in bytes, of |input|
// index: if the input is a font collection and index is specified, then
// the corresponding font will be returned, otherwise the whole
// collection. Ignored for non-collection fonts.
bool Process(OTSStream *output, const uint8_t *input, size_t length, uint32_t index = -1);
// This function will be called when OTS is reporting an error.
// level: the severity of the generated message:
// 0: error messages in case OTS fails to sanitize the font.
// 1: warning messages about issue OTS fixed in the sanitized font.
virtual void Message(int level, const char *format, ...) MSGFUNC_FMT_ATTR {}
// This function will be called when OTS needs to decide what to do for a
// font table.
// tag: table tag formed with OTS_TAG() macro
virtual TableAction GetTableAction(uint32_t tag) { return ots::TABLE_ACTION_DEFAULT; }
};
} // namespace ots
#endif // OPENTYPE_SANITISER_H_
// Copyright (c) 2009-2017 The OTS 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_MEMORY_STREAM_H_
#define OTS_MEMORY_STREAM_H_
#include <cstring>
#include <limits>
#include "opentype-sanitiser.h"
namespace ots {
class MemoryStream : public OTSStream {
public:
MemoryStream(void *ptr, size_t length)
: ptr_(ptr), length_(length), off_(0) {
}
virtual bool WriteRaw(const void *data, size_t length) {
if ((off_ + length > length_) ||
(length > std::numeric_limits<size_t>::max() - off_)) {
return false;
}
std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
off_ += length;
return true;
}
virtual bool Seek(off_t position) {
if (position < 0) return false;
if (static_cast<size_t>(position) > length_) return false;
off_ = position;
return true;
}
virtual off_t Tell() const {
return off_;
}
private:
void* const ptr_;
size_t length_;
off_t off_;
};
class ExpandingMemoryStream : public OTSStream {
public:
ExpandingMemoryStream(size_t initial, size_t limit)
: length_(initial), limit_(limit), off_(0) {
ptr_ = new uint8_t[length_];
}
~ExpandingMemoryStream() {
delete[] static_cast<uint8_t*>(ptr_);
}
void* get() const {
return ptr_;
}
bool WriteRaw(const void *data, size_t length) {
if ((off_ + length > length_) ||
(length > std::numeric_limits<size_t>::max() - off_)) {
if (length_ == limit_)
return false;
size_t new_length = (length_ + 1) * 2;
if (new_length < length_)
return false;
if (new_length > limit_)
new_length = limit_;
uint8_t* new_buf = new uint8_t[new_length];
std::memcpy(new_buf, ptr_, length_);
length_ = new_length;
delete[] static_cast<uint8_t*>(ptr_);
ptr_ = new_buf;
return WriteRaw(data, length);
}
std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
off_ += length;
return true;
}
bool Seek(off_t position) {
if (position < 0) return false;
if (static_cast<size_t>(position) > length_) return false;
off_ = position;
return true;
}
off_t Tell() const {
return off_;
}
private:
void* ptr_;
size_t length_;
const size_t limit_;
off_t off_;
};
} // namespace ots
#endif // OTS_MEMORY_STREAM_H_
This diff is collapsed.
// Copyright (c) 2009-2017 The OTS 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_CFF_H_
#define OTS_CFF_H_
#include "ots.h"
#include <map>
#include <string>
#include <vector>
namespace ots {
struct CFFIndex {
CFFIndex()
: count(0), off_size(0), offset_to_next(0) {}
uint16_t count;
uint8_t off_size;
std::vector<uint32_t> offsets;
uint32_t offset_to_next;
};
class OpenTypeCFF : public Table {
public:
explicit OpenTypeCFF(Font *font, uint32_t tag)
: Table(font, tag, tag),
font_dict_length(0),
local_subrs(NULL),
m_data(NULL),
m_length(0) {
}
~OpenTypeCFF();
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
// Name INDEX. This name is used in name.cc as a postscript font name.
std::string name;
// The number of fonts the file has.
size_t font_dict_length;
// A map from glyph # to font #.
std::map<uint16_t, uint8_t> fd_select;
// A list of char strings.
std::vector<CFFIndex *> char_strings_array;
// A list of Local Subrs associated with FDArrays. Can be empty.
std::vector<CFFIndex *> local_subrs_per_font;
// A Local Subrs associated with Top DICT. Can be NULL.
CFFIndex *local_subrs;
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_CFF_H_
This diff is collapsed.
// Copyright (c) 2010-2017 The OTS 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_CFF_TYPE2_CHARSTRING_H_
#define OTS_CFF_TYPE2_CHARSTRING_H_
#include "cff.h"
#include "ots.h"
#include <map>
#include <vector>
namespace ots {
// Validates all charstrings in |char_strings_index|. Charstring is a small
// language for font hinting defined in Adobe Technical Note #5177.
// http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf
//
// The validation will fail if one of the following conditions is met:
// 1. The code uses more than 48 values of argument stack.
// 2. The code uses deeply nested subroutine calls (more than 10 levels.)
// 3. The code passes invalid number of operands to an operator.
// 4. The code calls an undefined global or local subroutine.
// 5. The code uses one of the following operators that are unlikely used in
// an ordinary fonts, and could be dangerous: random, put, get, index, roll.
//
// Arguments:
// global_subrs_index: Global subroutines which could be called by a charstring
// in |char_strings_index|.
// fd_select: A map from glyph # to font #.
// local_subrs_per_font: A list of Local Subrs associated with FDArrays. Can be
// empty.
// local_subrs: A Local Subrs associated with Top DICT. Can be NULL.
// cff_table: A buffer which contains actual byte code of charstring, global
// subroutines and local subroutines.
bool ValidateType2CharStringIndex(
Font *font,
const CFFIndex &char_strings_index,
const CFFIndex &global_subrs_index,
const std::map<uint16_t, uint8_t> &fd_select,
const std::vector<CFFIndex *> &local_subrs_per_font,
const CFFIndex *local_subrs,
Buffer *cff_table);
// The list of Operators. See Appendix. A in Adobe Technical Note #5177.
enum Type2CharStringOperator {
kHStem = 1,
kVStem = 3,
kVMoveTo = 4,
kRLineTo = 5,
kHLineTo = 6,
kVLineTo = 7,
kRRCurveTo = 8,
kCallSubr = 10,
kReturn = 11,
kEndChar = 14,
kHStemHm = 18,
kHintMask = 19,
kCntrMask = 20,
kRMoveTo = 21,
kHMoveTo = 22,
kVStemHm = 23,
kRCurveLine = 24,
kRLineCurve = 25,
kVVCurveTo = 26,
kHHCurveTo = 27,
kCallGSubr = 29,
kVHCurveTo = 30,
kHVCurveTo = 31,
kDotSection = 12 << 8,
kAnd = (12 << 8) + 3,
kOr = (12 << 8) + 4,
kNot = (12 << 8) + 5,
kAbs = (12 << 8) + 9,
kAdd = (12 << 8) + 10,
kSub = (12 << 8) + 11,
kDiv = (12 << 8) + 12,
kNeg = (12 << 8) + 14,
kEq = (12 << 8) + 15,
kDrop = (12 << 8) + 18,
kPut = (12 << 8) + 20,
kGet = (12 << 8) + 21,
kIfElse = (12 << 8) + 22,
kRandom = (12 << 8) + 23,
kMul = (12 << 8) + 24,
kSqrt = (12 << 8) + 26,
kDup = (12 << 8) + 27,
kExch = (12 << 8) + 28,
kIndex = (12 << 8) + 29,
kRoll = (12 << 8) + 30,
kHFlex = (12 << 8) + 34,
kFlex = (12 << 8) + 35,
kHFlex1 = (12 << 8) + 36,
kFlex1 = (12 << 8) + 37,
// Operators that are undocumented, such as 'blend', will be rejected.
};
} // namespace ots
#endif // OTS_CFF_TYPE2_CHARSTRING_H_
This diff is collapsed.
// Copyright (c) 2009-2017 The OTS 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_CMAP_H_
#define OTS_CMAP_H_
#include <vector>
#include "ots.h"
namespace ots {
struct OpenTypeCMAPSubtableRange {
uint32_t start_range;
uint32_t end_range;
uint32_t start_glyph_id;
};
struct OpenTypeCMAPSubtableVSRange {
uint32_t unicode_value;
uint8_t additional_count;
};
struct OpenTypeCMAPSubtableVSMapping {
uint32_t unicode_value;
uint16_t glyph_id;
};
struct OpenTypeCMAPSubtableVSRecord {
uint32_t var_selector;
uint32_t default_offset;
uint32_t non_default_offset;
std::vector<OpenTypeCMAPSubtableVSRange> ranges;
std::vector<OpenTypeCMAPSubtableVSMapping> mappings;
};
class OpenTypeCMAP : public Table {
public:
explicit OpenTypeCMAP(Font *font, uint32_t tag)
: Table(font, tag, tag),
subtable_0_3_4_data(NULL),
subtable_0_3_4_length(0),
subtable_0_5_14_length(0),
subtable_3_0_4_data(NULL),
subtable_3_0_4_length(0),
subtable_3_1_4_data(NULL),
subtable_3_1_4_length(0) {
}
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
private:
// Platform 0, Encoding 3, Format 4, Unicode BMP table.
const uint8_t *subtable_0_3_4_data;
size_t subtable_0_3_4_length;
// Platform 0, Encoding 5, Format 14, Unicode Variation Sequence table.
size_t subtable_0_5_14_length;
std::vector<OpenTypeCMAPSubtableVSRecord> subtable_0_5_14;
// Platform 3, Encoding 0, Format 4, MS Symbol table.
const uint8_t *subtable_3_0_4_data;
size_t subtable_3_0_4_length;
// Platform 3, Encoding 1, Format 4, MS Unicode BMP table.
const uint8_t *subtable_3_1_4_data;
size_t subtable_3_1_4_length;
// Platform 3, Encoding 10, Format 12, MS Unicode UCS-4 table.
std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_12;
// Platform 3, Encoding 10, Format 13, MS UCS-4 Fallback table.
std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_13;
// Platform 1, Encoding 0, Format 0, Mac Roman table.
std::vector<uint8_t> subtable_1_0_0;
bool ParseFormat4(int platform, int encoding, const uint8_t *data,
size_t length, uint16_t num_glyphs);
bool Parse31012(const uint8_t *data, size_t length, uint16_t num_glyphs);
bool Parse31013(const uint8_t *data, size_t length, uint16_t num_glyphs);
bool Parse0514(const uint8_t *data, size_t length, uint16_t num_glyphs);
bool Parse100(const uint8_t *data, size_t length);
};
} // namespace ots
#endif
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cvt.h"
// cvt - Control Value Table
// http://www.microsoft.com/typography/otspec/cvt.htm
namespace ots {
bool OpenTypeCVT::Parse(const uint8_t *data, size_t length) {
Buffer table(data, length);
if (length >= 128 * 1024u) {
return Error("Length (%d) > 120K"); // almost all cvt tables are less than 4k bytes.
}
if (length % 2 != 0) {
return Error("Uneven table length (%d)", length);
}
if (!table.Skip(length)) {
return Error("Table length too high");
}
this->data = data;
this->length = length;
return true;
}
bool OpenTypeCVT::Serialize(OTSStream *out) {
if (!out->Write(this->data, this->length)) {
return Error("Failed to write cvt table");
}
return true;
}
bool OpenTypeCVT::ShouldSerialize() {
return Table::ShouldSerialize() &&
// this table is not for CFF fonts.
GetFont()->GetTable(OTS_TAG_GLYF) != NULL;
}
} // namespace ots
// Copyright (c) 2009-2017 The OTS 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_CVT_H_
#define OTS_CVT_H_
#include "ots.h"
namespace ots {
class OpenTypeCVT : public Table {
public:
explicit OpenTypeCVT(Font *font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
bool ShouldSerialize();
private:
const uint8_t *data;
uint32_t length;
};
} // namespace ots
#endif // OTS_CVT_H_
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "feat.h"
#include "name.h"
namespace ots {
bool OpenTypeFEAT::Parse(const uint8_t* data, size_t length) {
if (GetFont()->dropped_graphite) {
return Drop("Skipping Graphite table");
}
Buffer table(data, length);
if (!table.ReadU32(&this->version)) {
return DropGraphite("Failed to read version");
}
if (this->version >> 16 != 1 && this->version >> 16 != 2) {
return DropGraphite("Unsupported table version: %u", this->version >> 16);
}
if (!table.ReadU16(&this->numFeat)) {
return DropGraphite("Failed to read numFeat");
}
if (!table.ReadU16(&this->reserved)) {
return DropGraphite("Failed to read reserved");
}
if (this->reserved != 0) {
Warning("Nonzero reserved");
}
if (!table.ReadU32(&this->reserved2)) {
return DropGraphite("Failed to read valid reserved2");
}
if (this->reserved2 != 0) {
Warning("Nonzero reserved2");
}
std::unordered_set<size_t> unverified;
//this->features.resize(this->numFeat, this);
for (unsigned i = 0; i < this->numFeat; ++i) {
this->features.emplace_back(this);
FeatureDefn& feature = this->features[i];
if (!feature.ParsePart(table)) {
return DropGraphite("Failed to read features[%u]", i);
}
this->feature_ids.insert(feature.id);
for (unsigned j = 0; j < feature.numSettings; ++j) {
size_t offset = feature.offset + j * 4;
if (offset < feature.offset || offset > length) {
return DropGraphite("Invalid FeatSettingDefn offset %zu/%zu",
offset, length);
}
unverified.insert(offset);
// need to verify that this FeatureDefn points to valid
// FeatureSettingDefn
}
}
while (table.remaining()) {
bool used = unverified.erase(table.offset());
FeatureSettingDefn featSetting(this);
if (!featSetting.ParsePart(table, used)) {
return DropGraphite("Failed to read a FeatureSettingDefn");
}
featSettings.push_back(featSetting);
}
if (!unverified.empty()) {
return DropGraphite("%zu incorrect offsets into featSettings",
unverified.size());
}
if (table.remaining()) {
return Warning("%zu bytes unparsed", table.remaining());
}
return true;
}
bool OpenTypeFEAT::Serialize(OTSStream* out) {
if (!out->WriteU32(this->version) ||
!out->WriteU16(this->numFeat) ||
!out->WriteU16(this->reserved) ||
!out->WriteU32(this->reserved2) ||
!SerializeParts(this->features, out) ||
!SerializeParts(this->featSettings, out)) {
return Error("Failed to write table");
}
return true;
}
bool OpenTypeFEAT::IsValidFeatureId(uint32_t id) const {
return feature_ids.count(id);
}
bool OpenTypeFEAT::FeatureDefn::ParsePart(Buffer& table) {
OpenTypeNAME* name = static_cast<OpenTypeNAME*>(
parent->GetFont()->GetTypedTable(OTS_TAG_NAME));
if (!name) {
return parent->Error("FeatureDefn: Required name table is missing");
}
if (parent->version >> 16 >= 2 && !table.ReadU32(&this->id)) {
return parent->Error("FeatureDefn: Failed to read id");
}
if (parent->version >> 16 == 1) {
uint16_t id;
if (!table.ReadU16(&id)) {
return parent->Error("FeatureDefn: Failed to read id");
}
this->id = id;
}
if (!table.ReadU16(&this->numSettings)) {
return parent->Error("FeatureDefn: Failed to read numSettings");
}
if (parent->version >> 16 >= 2) {
if (!table.ReadU16(&this->reserved)) {
return parent->Error("FeatureDefn: Failed to read reserved");
}
if (this->reserved != 0) {
parent->Warning("FeatureDefn: Nonzero reserved");
}
}
if (!table.ReadU32(&this->offset)) {
return parent->Error("FeatureDefn: Failed to read offset");
} // validity of offset verified in OpenTypeFEAT::Parse
if (!table.ReadU16(&this->flags)) {
return parent->Error("FeatureDefn: Failed to read flags");
}
if ((this->flags & RESERVED) != 0) {
this->flags &= ~RESERVED;
parent->Warning("FeatureDefn: Nonzero (flags & 0x%x) repaired", RESERVED);
}
if (this->flags & HAS_DEFAULT_SETTING &&
(this->flags & DEFAULT_SETTING) >= this->numSettings) {
return parent->Error("FeatureDefn: (flags & 0x%x) is set but (flags & 0x%x "
"is not a valid setting index", HAS_DEFAULT_SETTING,
DEFAULT_SETTING);
}
if (!table.ReadU16(&this->label)) {
return parent->Error("FeatureDefn: Failed to read label");
}
if (!name->IsValidNameId(this->label)) {
if (this->id == 1 && name->IsValidNameId(this->label, true)) {
parent->Warning("FeatureDefn: Missing NameRecord repaired for feature"
" with id=%u, label=%u", this->id, this->label);
}
else {
return parent->Error("FeatureDefn: Invalid label");
}
}
return true;
}
bool OpenTypeFEAT::FeatureDefn::SerializePart(OTSStream* out) const {
if ((parent->version >> 16 >= 2 && !out->WriteU32(this->id)) ||
(parent->version >> 16 == 1 &&
!out->WriteU16(static_cast<uint16_t>(this->id))) ||
!out->WriteU16(this->numSettings) ||
(parent->version >> 16 >= 2 && !out->WriteU16(this->reserved)) ||
!out->WriteU32(this->offset) ||
!out->WriteU16(this->flags) ||
!out->WriteU16(this->label)) {
return parent->Error("FeatureDefn: Failed to write");
}
return true;
}
bool OpenTypeFEAT::FeatureSettingDefn::ParsePart(Buffer& table, bool used) {
OpenTypeNAME* name = static_cast<OpenTypeNAME*>(
parent->GetFont()->GetTypedTable(OTS_TAG_NAME));
if (!name) {
return parent->Error("FeatureSettingDefn: Required name table is missing");
}
if (!table.ReadS16(&this->value)) {
return parent->Error("FeatureSettingDefn: Failed to read value");
}
if (!table.ReadU16(&this->label) ||
(used && !name->IsValidNameId(this->label))) {
return parent->Error("FeatureSettingDefn: Failed to read valid label");
}
return true;
}
bool OpenTypeFEAT::FeatureSettingDefn::SerializePart(OTSStream* out) const {
if (!out->WriteS16(this->value) ||
!out->WriteU16(this->label)) {
return parent->Error("FeatureSettingDefn: Failed to write");
}
return true;
}
} // namespace ots
// Copyright (c) 2009-2017 The OTS 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_FEAT_H_
#define OTS_FEAT_H_
#include <vector>
#include <unordered_set>
#include "ots.h"
#include "graphite.h"
namespace ots {
class OpenTypeFEAT : public Table {
public:
explicit OpenTypeFEAT(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
bool IsValidFeatureId(uint32_t id) const;
private:
struct FeatureDefn : public TablePart<OpenTypeFEAT> {
explicit FeatureDefn(OpenTypeFEAT* parent)
: TablePart<OpenTypeFEAT>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
uint32_t id;
uint16_t numSettings;
uint16_t reserved;
uint32_t offset;
uint16_t flags;
static const uint16_t HAS_DEFAULT_SETTING = 0x4000;
static const uint16_t RESERVED = 0x3F00;
static const uint16_t DEFAULT_SETTING = 0x00FF;
uint16_t label;
};
struct FeatureSettingDefn : public TablePart<OpenTypeFEAT> {
explicit FeatureSettingDefn(OpenTypeFEAT* parent)
: TablePart<OpenTypeFEAT>(parent) { }
bool ParsePart(Buffer& table) { return ParsePart(table, true); }
bool ParsePart(Buffer& table, bool used);
bool SerializePart(OTSStream* out) const;
int16_t value;
uint16_t label;
};
uint32_t version;
uint16_t numFeat;
uint16_t reserved;
uint32_t reserved2;
std::vector<FeatureDefn> features;
std::vector<FeatureSettingDefn> featSettings;
std::unordered_set<uint32_t> feature_ids;
};
} // namespace ots
#endif // OTS_FEAT_H_
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fpgm.h"
// fpgm - Font Program
// http://www.microsoft.com/typography/otspec/fpgm.htm
namespace ots {
bool OpenTypeFPGM::Parse(const uint8_t *data, size_t length) {
Buffer table(data, length);
if (length >= 128 * 1024u) {
return Error("length (%ld) > 120", length); // almost all fpgm tables are less than 5k bytes.
}
if (!table.Skip(length)) {
return Error("Bad table length");
}
this->data = data;
this->length = length;
return true;
}
bool OpenTypeFPGM::Serialize(OTSStream *out) {
if (!out->Write(this->data, this->length)) {
return Error("Failed to write fpgm table");
}
return true;
}
bool OpenTypeFPGM::ShouldSerialize() {
return Table::ShouldSerialize() &&
// this table is not for CFF fonts.
GetFont()->GetTable(OTS_TAG_GLYF) != NULL;
}
} // namespace ots
// Copyright (c) 2009-2017 The OTS 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_FPGM_H_
#define OTS_FPGM_H_
#include "ots.h"
namespace ots {
class OpenTypeFPGM : public Table {
public:
explicit OpenTypeFPGM(Font *font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
bool ShouldSerialize();
private:
const uint8_t *data;
uint32_t length;
};
} // namespace ots
#endif // OTS_FPGM_H_
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gasp.h"
// gasp - Grid-fitting And Scan-conversion Procedure
// http://www.microsoft.com/typography/otspec/gasp.htm
namespace ots {
bool OpenTypeGASP::Parse(const uint8_t *data, size_t length) {
Buffer table(data, length);
uint16_t num_ranges = 0;
if (!table.ReadU16(&this->version) ||
!table.ReadU16(&num_ranges)) {
return Error("Failed to read table header");
}
if (this->version > 1) {
// Lots of Linux fonts have bad version numbers...
return Drop("Unsupported version: %u", this->version);
}
if (num_ranges == 0) {
return Drop("numRanges is zero");
}
this->gasp_ranges.reserve(num_ranges);
for (unsigned i = 0; i < num_ranges; ++i) {
uint16_t max_ppem = 0;
uint16_t behavior = 0;
if (!table.ReadU16(&max_ppem) ||
!table.ReadU16(&behavior)) {
return Error("Failed to read GASPRANGE %d", i);
}
if ((i > 0) && (this->gasp_ranges[i - 1].first >= max_ppem)) {
// The records in the gaspRange[] array must be sorted in order of
// increasing rangeMaxPPEM value.
return Drop("Ranges are not sorted");
}
if ((i == num_ranges - 1u) && // never underflow.
(max_ppem != 0xffffu)) {
return Drop("The last record should be 0xFFFF as a sentinel value "
"for rangeMaxPPEM");
}
if (behavior >> 8) {
Warning("Undefined bits are used: %x", behavior);
// mask undefined bits.
behavior &= 0x000fu;
}
if (this->version == 0 && (behavior >> 2) != 0) {
Warning("Changed the version number to 1");
this->version = 1;
}
this->gasp_ranges.push_back(std::make_pair(max_ppem, behavior));
}
return true;
}
bool OpenTypeGASP::Serialize(OTSStream *out) {
const uint16_t num_ranges = static_cast<uint16_t>(this->gasp_ranges.size());
if (num_ranges != this->gasp_ranges.size() ||
!out->WriteU16(this->version) ||
!out->WriteU16(num_ranges)) {
return Error("Failed to write table header");
}
for (uint16_t i = 0; i < num_ranges; ++i) {
if (!out->WriteU16(this->gasp_ranges[i].first) ||
!out->WriteU16(this->gasp_ranges[i].second)) {
return Error("Failed to write GASPRANGE %d", i);
}
}
return true;
}
} // namespace ots
// Copyright (c) 2009-2017 The OTS 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_GASP_H_
#define OTS_GASP_H_
#include <new>
#include <utility>
#include <vector>
#include "ots.h"
namespace ots {
class OpenTypeGASP : public Table {
public:
explicit OpenTypeGASP(Font *font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
private:
uint16_t version;
// A array of (max PPEM, GASP behavior) pairs.
std::vector<std::pair<uint16_t, uint16_t> > gasp_ranges;
};
} // namespace ots
#endif // OTS_GASP_H_
This diff is collapsed.
// Copyright (c) 2011-2017 The OTS 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_GDEF_H_
#define OTS_GDEF_H_
#include "ots.h"
namespace ots {
class OpenTypeGDEF : public Table {
public:
explicit OpenTypeGDEF(Font *font, uint32_t tag)
: Table(font, tag, tag),
version_2(false),
has_glyph_class_def(false),
has_mark_attachment_class_def(false),
has_mark_glyph_sets_def(false),
num_mark_glyph_sets(0),
m_data(NULL),
m_length(0),
m_num_glyphs(0) {
}
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
bool version_2;
bool has_glyph_class_def;
bool has_mark_attachment_class_def;
bool has_mark_glyph_sets_def;
uint16_t num_mark_glyph_sets;
private:
bool ParseAttachListTable(const uint8_t *data, size_t length);
bool ParseLigCaretListTable(const uint8_t *data, size_t length);
bool ParseMarkGlyphSetsDefTable(const uint8_t *data, size_t length);
const uint8_t *m_data;
size_t m_length;
uint16_t m_num_glyphs;
};
} // namespace ots
#endif
This diff is collapsed.
// Copyright (c) 2009-2017 The OTS 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_GLAT_H_
#define OTS_GLAT_H_
#include <vector>
#include "ots.h"
#include "graphite.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeGLAT_Basic Interface
// -----------------------------------------------------------------------------
class OpenTypeGLAT_Basic : public Table {
public:
explicit OpenTypeGLAT_Basic(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
virtual bool Parse(const uint8_t* data, size_t length) = 0;
virtual bool Serialize(OTSStream* out) = 0;
};
// -----------------------------------------------------------------------------
// OpenTypeGLAT_v1
// -----------------------------------------------------------------------------
class OpenTypeGLAT_v1 : public OpenTypeGLAT_Basic {
public:
explicit OpenTypeGLAT_v1(Font* font, uint32_t tag)
: OpenTypeGLAT_Basic(font, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
struct GlatEntry : public TablePart<OpenTypeGLAT_v1> {
explicit GlatEntry(OpenTypeGLAT_v1* parent)
: TablePart<OpenTypeGLAT_v1>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
uint8_t attNum;
uint8_t num;
std::vector<int16_t> attributes;
};
uint32_t version;
std::vector<GlatEntry> entries;
};
// -----------------------------------------------------------------------------
// OpenTypeGLAT_v2
// -----------------------------------------------------------------------------
class OpenTypeGLAT_v2 : public OpenTypeGLAT_Basic {
public:
explicit OpenTypeGLAT_v2(Font* font, uint32_t tag)
: OpenTypeGLAT_Basic(font, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
struct GlatEntry : public TablePart<OpenTypeGLAT_v2> {
explicit GlatEntry(OpenTypeGLAT_v2* parent)
: TablePart<OpenTypeGLAT_v2>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
int16_t attNum;
int16_t num;
std::vector<int16_t> attributes;
};
uint32_t version;
std::vector<GlatEntry> entries;
};
// -----------------------------------------------------------------------------
// OpenTypeGLAT_v3
// -----------------------------------------------------------------------------
class OpenTypeGLAT_v3 : public OpenTypeGLAT_Basic {
public:
explicit OpenTypeGLAT_v3(Font* font, uint32_t tag)
: OpenTypeGLAT_Basic(font, tag) { }
bool Parse(const uint8_t* data, size_t length) {
return this->Parse(data, length, false);
}
bool Serialize(OTSStream* out);
private:
bool Parse(const uint8_t* data, size_t length, bool prevent_decompression);
struct GlyphAttrs : public TablePart<OpenTypeGLAT_v3> {
explicit GlyphAttrs(OpenTypeGLAT_v3* parent)
: TablePart<OpenTypeGLAT_v3>(parent), octabox(parent) { }
bool ParsePart(Buffer& table) { return false; }
bool ParsePart(Buffer& table, const size_t size);
bool SerializePart(OTSStream* out) const;
struct OctaboxMetrics : public TablePart<OpenTypeGLAT_v3> {
explicit OctaboxMetrics(OpenTypeGLAT_v3* parent)
: TablePart<OpenTypeGLAT_v3>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
struct SubboxEntry : public TablePart<OpenTypeGLAT_v3> {
explicit SubboxEntry(OpenTypeGLAT_v3* parent)
: TablePart<OpenTypeGLAT_v3>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
uint8_t left;
uint8_t right;
uint8_t bottom;
uint8_t top;
uint8_t diag_pos_min;
uint8_t diag_pos_max;
uint8_t diag_neg_min;
uint8_t diag_neg_max;
};
uint16_t subbox_bitmap;
uint8_t diag_neg_min;
uint8_t diag_neg_max;
uint8_t diag_pos_min;
uint8_t diag_pos_max;
std::vector<SubboxEntry> subboxes;
};
struct GlatEntry : public TablePart<OpenTypeGLAT_v3> {
explicit GlatEntry(OpenTypeGLAT_v3* parent)
: TablePart<OpenTypeGLAT_v3>(parent) { }
bool ParsePart(Buffer& table);
bool SerializePart(OTSStream* out) const;
int16_t attNum;
int16_t num;
std::vector<int16_t> attributes;
};
OctaboxMetrics octabox;
std::vector<GlatEntry> entries;
};
uint32_t version;
uint32_t compHead; // compression header
static const uint32_t SCHEME = 0xF8000000;
static const uint32_t FULL_SIZE = 0x07FFFFFF;
static const uint32_t RESERVED = 0x07FFFFFE;
static const uint32_t OCTABOXES = 0x00000001;
std::vector<GlyphAttrs> entries;
};
// -----------------------------------------------------------------------------
// OpenTypeGLAT
// -----------------------------------------------------------------------------
class OpenTypeGLAT : public Table {
public:
explicit OpenTypeGLAT(Font* font, uint32_t tag)
: Table(font, tag, tag), font(font), tag(tag) { }
OpenTypeGLAT(const OpenTypeGLAT& other) = delete;
OpenTypeGLAT& operator=(const OpenTypeGLAT& other) = delete;
~OpenTypeGLAT() { delete handler; }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
Font* font;
uint32_t tag;
OpenTypeGLAT_Basic* handler = nullptr;
};
} // namespace ots
#endif // OTS_GLAT_H_
// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gloc.h"
#include "name.h"
namespace ots {
bool OpenTypeGLOC::Parse(const uint8_t* data, size_t length) {
if (GetFont()->dropped_graphite) {
return Drop("Skipping Graphite table");
}
Buffer table(data, length);
OpenTypeNAME* name = static_cast<OpenTypeNAME*>(
GetFont()->GetTypedTable(OTS_TAG_NAME));
if (!name) {
return DropGraphite("Required name table is missing");
}
if (!table.ReadU32(&this->version)) {
return DropGraphite("Failed to read version");
}
if (this->version >> 16 != 1) {
return DropGraphite("Unsupported table version: %u", this->version >> 16);
}
if (!table.ReadU16(&this->flags) || this->flags > 0b11) {
return DropGraphite("Failed to read valid flags");
}
if (!table.ReadU16(&this->numAttribs)) {
return DropGraphite("Failed to read numAttribs");
}
if (this->flags & ATTRIB_IDS && this->numAttribs * sizeof(uint16_t) >
table.remaining()) {
return DropGraphite("Failed to calulate length of locations");
}
size_t locations_len = (table.remaining() -
(this->flags & ATTRIB_IDS ? this->numAttribs * sizeof(uint16_t) : 0)) /
(this->flags & LONG_FORMAT ? sizeof(uint32_t) : sizeof(uint16_t));
//this->locations.resize(locations_len);
if (this->flags & LONG_FORMAT) {
unsigned long last_location = 0;
for (size_t i = 0; i < locations_len; ++i) {
this->locations.emplace_back();
uint32_t& location = this->locations[i];
if (!table.ReadU32(&location) || location < last_location) {
return DropGraphite("Failed to read valid locations[%lu]", i);
}
last_location = location;
}
} else { // short (16-bit) offsets
unsigned last_location = 0;
for (size_t i = 0; i < locations_len; ++i) {
uint16_t location;
if (!table.ReadU16(&location) || location < last_location) {
return DropGraphite("Failed to read valid locations[%lu]", i);
}
last_location = location;
this->locations.push_back(static_cast<uint32_t>(location));
}
}
if (this->locations.empty()) {
return DropGraphite("No locations");
}
if (this->flags & ATTRIB_IDS) { // attribIds array present
//this->attribIds.resize(numAttribs);
for (unsigned i = 0; i < this->numAttribs; ++i) {
this->attribIds.emplace_back();
if (!table.ReadU16(&this->attribIds[i]) ||
!name->IsValidNameId(this->attribIds[i])) {
return DropGraphite("Failed to read valid attribIds[%u]", i);
}
}
}
if (table.remaining()) {
return Warning("%zu bytes unparsed", table.remaining());
}
return true;
}
bool OpenTypeGLOC::Serialize(OTSStream* out) {
if (!out->WriteU32(this->version) ||
!out->WriteU16(this->flags) ||
!out->WriteU16(this->numAttribs) ||
(this->flags & LONG_FORMAT ? !SerializeParts(this->locations, out) :
![&] {
for (uint32_t location : this->locations) {
if (!out->WriteU16(static_cast<uint16_t>(location))) {
return false;
}
}
return true;
}()) ||
(this->flags & ATTRIB_IDS && !SerializeParts(this->attribIds, out))) {
return Error("Failed to write table");
}
return true;
}
const std::vector<uint32_t>& OpenTypeGLOC::GetLocations() {
return this->locations;
}
} // namespace ots
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright (c) 2009-2017 The OTS 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_HHEA_H_
#define OTS_HHEA_H_
#include "metrics.h"
#include "ots.h"
namespace ots {
class OpenTypeHHEA : public OpenTypeMetricsHeader {
public:
explicit OpenTypeHHEA(Font *font, uint32_t tag)
: OpenTypeMetricsHeader(font, tag, tag) { }
bool Parse(const uint8_t *data, size_t length);
bool Serialize(OTSStream *out);
};
} // namespace ots
#endif // OTS_HHEA_H_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment