mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 699420 - Update OTS to r74; r=jfkthame
This commit is contained in:
parent
2e4e1bd781
commit
4951063a0d
@ -1,10 +1,8 @@
|
||||
This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
|
||||
|
||||
Current revision: r62
|
||||
Current revision: r74
|
||||
|
||||
Applied local patches:
|
||||
ots-fix-vc10.patch - workaround for VS10 STL wrappers (bug 602558)
|
||||
|
||||
ots-fix-gcc46.patch - fix os2.cc compile error for GCC 4.6 (bug 628252)
|
||||
|
||||
ots-fix-sparc64.patch - fix alignment error on sparc64 (bug 643137)
|
||||
|
@ -22,6 +22,7 @@ typedef unsigned __int64 uint64_t;
|
||||
|
||||
#include <algorithm> // for std::min
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
namespace ots {
|
||||
|
@ -1,18 +0,0 @@
|
||||
diff --git a/gfx/ots/src/os2.cc b/gfx/ots/src/os2.cc
|
||||
--- a/gfx/ots/src/os2.cc
|
||||
+++ b/gfx/ots/src/os2.cc
|
||||
@@ -1,12 +1,14 @@
|
||||
// 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.
|
||||
|
||||
+#include <cstddef>
|
||||
+
|
||||
#include "os2.h"
|
||||
|
||||
#include "head.h"
|
||||
|
||||
// OS/2 - OS/2 and Windows Metrics
|
||||
// http://www.microsoft.com/opentype/otspec/os2.htm
|
||||
|
||||
namespace ots {
|
@ -189,13 +189,15 @@ bool ParseDictDataBcd(
|
||||
if ((nibble & 0xf) == 0xf) {
|
||||
// TODO(yusukes): would be better to store actual double value,
|
||||
// rather than the dummy integer.
|
||||
operands->push_back(std::make_pair(0, DICT_OPERAND_REAL));
|
||||
operands->push_back(std::make_pair(static_cast<uint32_t>(0),
|
||||
DICT_OPERAND_REAL));
|
||||
return true;
|
||||
}
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
if ((nibble & 0x0f) == 0x0f) {
|
||||
operands->push_back(std::make_pair(0, DICT_OPERAND_REAL));
|
||||
operands->push_back(std::make_pair(static_cast<uint32_t>(0),
|
||||
DICT_OPERAND_REAL));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -264,7 +266,8 @@ bool ParseDictDataNumber(
|
||||
!table->ReadU8(&b2)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
operands->push_back(std::make_pair((b1 << 8) + b2, DICT_OPERAND_INTEGER));
|
||||
operands->push_back(std::make_pair(
|
||||
static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
|
||||
return true;
|
||||
|
||||
case 29: // longint
|
||||
@ -275,7 +278,8 @@ bool ParseDictDataNumber(
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
operands->push_back(std::make_pair(
|
||||
(b1 << 24) + (b2 << 16) + (b3 << 8) + b4, DICT_OPERAND_INTEGER));
|
||||
static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4),
|
||||
DICT_OPERAND_INTEGER));
|
||||
return true;
|
||||
|
||||
case 30: // binary coded decimal
|
||||
@ -317,7 +321,8 @@ bool ParseDictDataReadNext(
|
||||
if (op == 12) {
|
||||
return ParseDictDataEscapedOperator(table, operands);
|
||||
}
|
||||
operands->push_back(std::make_pair(op, DICT_OPERATOR));
|
||||
operands->push_back(std::make_pair(
|
||||
static_cast<uint32_t>(op), DICT_OPERATOR));
|
||||
return true;
|
||||
} else if (op <= 27 || op == 31 || op == 255) {
|
||||
// reserved area.
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "cmap.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -694,9 +695,10 @@ bool ots_cmap_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
continue;
|
||||
}
|
||||
overlap_checker.push_back(
|
||||
std::make_pair(subtable_headers[i].offset, 1 /* start */));
|
||||
std::make_pair(subtable_headers[i].offset,
|
||||
static_cast<uint8_t>(1) /* start */));
|
||||
overlap_checker.push_back(
|
||||
std::make_pair(end_byte, 0 /* end */));
|
||||
std::make_pair(end_byte, static_cast<uint8_t>(0) /* end */));
|
||||
}
|
||||
std::sort(overlap_checker.begin(), overlap_checker.end());
|
||||
int overlap_count = 0;
|
||||
|
@ -42,7 +42,8 @@ bool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
!subtable.ReadU16(&glyph_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned attach_points_end = static_cast<unsigned>(4) + 2*glyph_count;
|
||||
const unsigned attach_points_end =
|
||||
2 * static_cast<unsigned>(glyph_count) + 4;
|
||||
if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -110,7 +111,8 @@ bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
!subtable.ReadU16(&lig_glyph_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned lig_glyphs_end = static_cast<unsigned>(4) + 2*lig_glyph_count;
|
||||
const unsigned lig_glyphs_end =
|
||||
2 * static_cast<unsigned>(lig_glyph_count) + 4;
|
||||
if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -155,7 +157,7 @@ bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
std::vector<uint16_t> caret_values;
|
||||
caret_values.resize(caret_count);
|
||||
uint16_t last_offset_caret = 0;
|
||||
unsigned caret_values_end = static_cast<unsigned>(2) + 2*caret_count;
|
||||
unsigned caret_values_end = 2 * static_cast<unsigned>(caret_count) + 2;
|
||||
for (unsigned j = 0; j < caret_count; ++j) {
|
||||
if (!subtable.ReadU16(&caret_values[j])) {
|
||||
return OTS_FAILURE();
|
||||
@ -215,7 +217,7 @@ bool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned mark_sets_end = static_cast<unsigned>(4) + 2*mark_set_count;
|
||||
const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4;
|
||||
if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -288,11 +290,9 @@ bool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned gdef_header_end = static_cast<unsigned>(8) +
|
||||
gdef->version_2 ? static_cast<unsigned>(2) : static_cast<unsigned>(0);
|
||||
if (gdef_header_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
unsigned gdef_header_end = 8;
|
||||
if (gdef->version_2)
|
||||
gdef_header_end += 2;
|
||||
|
||||
// Parse subtables
|
||||
if (offset_glyph_class_def) {
|
||||
|
@ -111,13 +111,16 @@ bool ParseSimpleGlyph(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
|
||||
if (ots::g_transcode_hints) {
|
||||
glyf->iov.push_back(std::make_pair(
|
||||
data + gly_offset, gly_header_length + bytecode_length));
|
||||
data + gly_offset,
|
||||
static_cast<size_t>(gly_header_length + bytecode_length)));
|
||||
} else {
|
||||
// enqueue two vectors: the glyph data up to the bytecode length, then
|
||||
// a pointer to a static uint16_t 0 to overwrite the length.
|
||||
glyf->iov.push_back(std::make_pair(
|
||||
data + gly_offset, gly_header_length - 2));
|
||||
glyf->iov.push_back(std::make_pair((const uint8_t*) "\x00\x00", 2));
|
||||
data + gly_offset,
|
||||
static_cast<size_t>(gly_header_length - 2)));
|
||||
glyf->iov.push_back(std::make_pair((const uint8_t*) "\x00\x00",
|
||||
static_cast<size_t>(2)));
|
||||
}
|
||||
|
||||
if (!table->Skip(bytecode_length)) {
|
||||
@ -153,7 +156,7 @@ bool ParseSimpleGlyph(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
|
||||
glyf->iov.push_back(std::make_pair(
|
||||
data + gly_offset + gly_header_length + bytecode_length,
|
||||
flags_count_physical + xy_coordinates_length));
|
||||
static_cast<size_t>(flags_count_physical + xy_coordinates_length)));
|
||||
|
||||
*new_size
|
||||
= gly_header_length + flags_count_physical + xy_coordinates_length;
|
||||
@ -247,7 +250,8 @@ bool ots_glyf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
}
|
||||
} else {
|
||||
// it's a composite glyph without any bytecode. Enqueue the whole thing
|
||||
glyf->iov.push_back(std::make_pair(data + gly_offset, gly_length));
|
||||
glyf->iov.push_back(std::make_pair(data + gly_offset,
|
||||
static_cast<size_t>(gly_length)));
|
||||
new_size = gly_length;
|
||||
}
|
||||
|
||||
@ -258,7 +262,8 @@ bool ots_glyf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
const unsigned padding = (4 - (new_size & 3)) % 4;
|
||||
if (padding) {
|
||||
glyf->iov.push_back(std::make_pair(
|
||||
reinterpret_cast<const uint8_t*>("\x00\x00\x00\x00"), padding));
|
||||
reinterpret_cast<const uint8_t*>("\x00\x00\x00\x00"),
|
||||
static_cast<size_t>(padding)));
|
||||
new_size += padding;
|
||||
}
|
||||
current_offset += new_size;
|
||||
|
@ -171,7 +171,7 @@ bool ParseMarkArrayTable(const uint8_t *data, const size_t length,
|
||||
}
|
||||
|
||||
// MarkRecord consists of 4-bytes.
|
||||
const unsigned mark_records_end = static_cast<unsigned>(2) + mark_count * 4;
|
||||
const unsigned mark_records_end = 4 * static_cast<unsigned>(mark_count) + 2;
|
||||
if (mark_records_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -289,8 +289,7 @@ bool ParsePairPosFormat1(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned pair_pos_end = static_cast<unsigned>(10) +
|
||||
pair_set_count * 2;
|
||||
const unsigned pair_pos_end = 2 * static_cast<unsigned>(pair_set_count) + 10;
|
||||
if (pair_pos_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -432,8 +431,8 @@ bool ParseCursiveAttachment(const ots::OpenTypeFile *file, const uint8_t *data,
|
||||
}
|
||||
|
||||
// Check entry exit records.
|
||||
const unsigned entry_exit_records_end = static_cast<unsigned>(6) +
|
||||
entry_exit_count * 2;
|
||||
const unsigned entry_exit_records_end =
|
||||
2 * static_cast<unsigned>(entry_exit_count) + 6;
|
||||
if (entry_exit_records_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -488,8 +487,8 @@ bool ParseAnchorArrayTable(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned anchor_array_end = static_cast<unsigned>(2) +
|
||||
record_count * class_count * 2;
|
||||
const unsigned anchor_array_end = 2 * static_cast<unsigned>(record_count) *
|
||||
static_cast<unsigned>(class_count) + 2;
|
||||
if (anchor_array_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
@ -392,24 +392,6 @@ bool ParseLigatureSubstitution(const ots::OpenTypeFile *file,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseSubstLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs,
|
||||
const uint16_t num_lookups) {
|
||||
uint16_t sequence_index = 0;
|
||||
uint16_t lookup_list_index = 0;
|
||||
|
||||
if (!subtable->ReadU16(&sequence_index) ||
|
||||
!subtable->ReadU16(&lookup_list_index)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
if (sequence_index >= num_glyphs) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
if (lookup_list_index >= num_lookups) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lookup Type 5:
|
||||
// Contextual Substitution Subtable
|
||||
bool ParseContextSubstitution(const ots::OpenTypeFile *file,
|
||||
|
@ -97,8 +97,8 @@ bool ParseScriptTable(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned lang_sys_record_end = static_cast<unsigned>(4) +
|
||||
lang_sys_count * 6;
|
||||
const unsigned lang_sys_record_end =
|
||||
6 * static_cast<unsigned>(lang_sys_count) + 4;
|
||||
if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -146,8 +146,8 @@ bool ParseFeatureTable(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned feature_table_end = static_cast<unsigned>(4) +
|
||||
num_lookups * 2;
|
||||
const unsigned feature_table_end =
|
||||
2 * static_cast<unsigned>(num_lookups) + 4;
|
||||
if (feature_table_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -210,9 +210,8 @@ bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data,
|
||||
subtables.reserve(subtable_count);
|
||||
// If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
|
||||
// extra 2 bytes will follow after subtable offset array.
|
||||
const unsigned lookup_table_end =
|
||||
static_cast<unsigned>(use_mark_filtering_set ? 8 : 6) +
|
||||
subtable_count * 2;
|
||||
const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) +
|
||||
(use_mark_filtering_set ? 8 : 6);
|
||||
if (lookup_table_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -471,8 +470,7 @@ bool ParseRuleSetTable(const uint8_t *data, const size_t length,
|
||||
if (!subtable.ReadU16(&rule_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned rule_end = static_cast<unsigned>(2) +
|
||||
rule_count * 2;
|
||||
const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2;
|
||||
if (rule_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -578,8 +576,8 @@ bool ParseClassSetTable(const uint8_t *data, const size_t length,
|
||||
if (!subtable.ReadU16(&class_rule_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned class_rule_end = static_cast<unsigned>(2) +
|
||||
class_rule_count * 2;
|
||||
const unsigned class_rule_end =
|
||||
2 * static_cast<unsigned>(class_rule_count) + 2;
|
||||
if (class_rule_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -617,8 +615,7 @@ bool ParseContextFormat2(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned class_set_end = static_cast<unsigned>(8) +
|
||||
class_set_cnt * 2;
|
||||
const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8;
|
||||
if (class_set_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -676,8 +673,8 @@ bool ParseContextFormat3(const uint8_t *data, const size_t length,
|
||||
if (glyph_count >= num_glyphs) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned lookup_record_end = static_cast<unsigned>(6) +
|
||||
glyph_count * 2 + lookup_count * 4;
|
||||
const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) +
|
||||
4 * static_cast<unsigned>(lookup_count) + 6;
|
||||
if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -784,8 +781,8 @@ bool ParseChainRuleSetTable(const uint8_t *data, const size_t length,
|
||||
if (!subtable.ReadU16(&chain_rule_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned chain_rule_end = static_cast<unsigned>(2) +
|
||||
chain_rule_count * 2;
|
||||
const unsigned chain_rule_end =
|
||||
2 * static_cast<unsigned>(chain_rule_count) + 2;
|
||||
if (chain_rule_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -821,8 +818,8 @@ bool ParseChainContextFormat1(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned chain_rule_set_end = static_cast<unsigned>(6) +
|
||||
chain_rule_set_count * 2;
|
||||
const unsigned chain_rule_set_end =
|
||||
2 * static_cast<unsigned>(chain_rule_set_count) + 6;
|
||||
if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -916,8 +913,8 @@ bool ParseChainClassSetTable(const uint8_t *data, const size_t length,
|
||||
if (!subtable.ReadU16(&chain_class_rule_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const unsigned chain_class_rule_end = static_cast<unsigned>(2) +
|
||||
chain_class_rule_count * 2;
|
||||
const unsigned chain_class_rule_end =
|
||||
2 * static_cast<unsigned>(chain_class_rule_count) + 2;
|
||||
if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -960,8 +957,8 @@ bool ParseChainContextFormat2(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned chain_class_set_end = static_cast<unsigned>(12) +
|
||||
chain_class_set_count * 2;
|
||||
const unsigned chain_class_set_end =
|
||||
2 * static_cast<unsigned>(chain_class_set_count) + 12;
|
||||
if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -1108,8 +1105,11 @@ bool ParseChainContextFormat3(const uint8_t *data, const size_t length,
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned lookup_record_end = static_cast<unsigned>(10) +
|
||||
(backtrack_count + input_count + lookahead_count) * 2 + lookup_count * 4;
|
||||
const unsigned lookup_record_end =
|
||||
2 * (static_cast<unsigned>(backtrack_count) +
|
||||
static_cast<unsigned>(input_count) +
|
||||
static_cast<unsigned>(lookahead_count)) +
|
||||
4 * static_cast<unsigned>(lookup_count) + 10;
|
||||
if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -1175,8 +1175,8 @@ bool ParseScriptListTable(const uint8_t *data, const size_t length,
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
const unsigned script_record_end = static_cast<unsigned>(2) +
|
||||
script_count * 6;
|
||||
const unsigned script_record_end =
|
||||
6 * static_cast<unsigned>(script_count) + 2;
|
||||
if (script_record_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -1232,8 +1232,8 @@ bool ParseFeatureListTable(const uint8_t *data, const size_t length,
|
||||
|
||||
std::vector<FeatureRecord> feature_records;
|
||||
feature_records.resize(feature_count);
|
||||
const unsigned feature_record_end = static_cast<unsigned>(2) +
|
||||
feature_count * 6;
|
||||
const unsigned feature_record_end =
|
||||
6 * static_cast<unsigned>(feature_count) + 2;
|
||||
if (feature_record_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
@ -1282,8 +1282,8 @@ bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data,
|
||||
|
||||
std::vector<uint16_t> lookups;
|
||||
lookups.reserve(*num_lookups);
|
||||
const unsigned lookup_end = static_cast<unsigned>(2) +
|
||||
(*num_lookups) * 2;
|
||||
const unsigned lookup_end =
|
||||
2 * static_cast<unsigned>(*num_lookups) + 2;
|
||||
if (lookup_end > std::numeric_limits<uint16_t>::max()) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2011 Mozilla Foundation. All rights reserved.
|
||||
// Copyright (c) 2011 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.
|
||||
|
||||
@ -12,173 +12,179 @@
|
||||
// name - Naming Table
|
||||
// http://www.microsoft.com/opentype/otspec/name.htm
|
||||
|
||||
namespace { // misc local helper functions
|
||||
namespace {
|
||||
|
||||
inline bool
|
||||
valid_in_ps_name(char c) {
|
||||
bool ValidInPsName(char c) {
|
||||
return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c));
|
||||
}
|
||||
|
||||
inline bool
|
||||
check_ps_name_ascii(std::string& name) {
|
||||
for (unsigned int i = 0; i < name.size(); ++i) {
|
||||
if (!valid_in_ps_name(name[i])) {
|
||||
bool CheckPsNameAscii(const std::string& name) {
|
||||
for (unsigned i = 0; i < name.size(); ++i) {
|
||||
if (!ValidInPsName(name[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
check_ps_name_utf16_be(std::string& name) {
|
||||
for (unsigned int i = 0; i < name.size(); i += 2) {
|
||||
bool CheckPsNameUtf16Be(const std::string& name) {
|
||||
if ((name.size() & 1) != 0)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < name.size(); i += 2) {
|
||||
if (name[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
if (!valid_in_ps_name(name[i+1])) {
|
||||
if (!ValidInPsName(name[i+1])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
assign_to_utf16_be_from_ascii(std::string& target, const std::string& source) {
|
||||
target.resize(source.size() * 2);
|
||||
for (unsigned int i = 0, j = 0; i < source.size(); i++) {
|
||||
target[j++] = '\0';
|
||||
target[j++] = source[i];
|
||||
void AssignToUtf16BeFromAscii(std::string* target,
|
||||
const std::string& source) {
|
||||
target->resize(source.size() * 2);
|
||||
for (unsigned i = 0, j = 0; i < source.size(); i++) {
|
||||
(*target)[j++] = '\0';
|
||||
(*target)[j++] = source[i];
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace ots {
|
||||
|
||||
bool ots_name_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) {
|
||||
Buffer table(data, length);
|
||||
|
||||
OpenTypeNAME *name = new OpenTypeNAME;
|
||||
OpenTypeNAME* name = new OpenTypeNAME;
|
||||
file->name = name;
|
||||
|
||||
uint16_t format;
|
||||
uint16_t format = 0;
|
||||
if (!table.ReadU16(&format) || format > 1) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
uint16_t count;
|
||||
uint16_t count = 0;
|
||||
if (!table.ReadU16(&count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
uint16_t stringOffset;
|
||||
if (!table.ReadU16(&stringOffset) || stringOffset > length) {
|
||||
uint16_t string_offset = 0;
|
||||
if (!table.ReadU16(&string_offset) || string_offset > length) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
const char* stringBase = (const char*)data + stringOffset;
|
||||
const char* string_base = reinterpret_cast<const char*>(data) +
|
||||
string_offset;
|
||||
|
||||
NameRecord prevRec;
|
||||
bool sortRequired = false;
|
||||
NameRecord prev_record;
|
||||
bool sort_required = false;
|
||||
|
||||
// Read all the names, discarding any with invalid IDs,
|
||||
// and any where the offset/length would be outside the table.
|
||||
// A stricter alternative would be to reject the font if there
|
||||
// are invalid name records, but it's not clear that is necessary.
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
NameRecord rec;
|
||||
uint16_t nameLength, nameOffset;
|
||||
if (!table.ReadU16(&rec.platformID) ||
|
||||
!table.ReadU16(&rec.encodingID) ||
|
||||
!table.ReadU16(&rec.languageID) ||
|
||||
!table.ReadU16(&rec.nameID) ||
|
||||
!table.ReadU16(&nameLength) ||
|
||||
!table.ReadU16(&nameOffset)) {
|
||||
uint16_t name_length, name_offset;
|
||||
if (!table.ReadU16(&rec.platform_id) ||
|
||||
!table.ReadU16(&rec.encoding_id) ||
|
||||
!table.ReadU16(&rec.language_id) ||
|
||||
!table.ReadU16(&rec.name_id) ||
|
||||
!table.ReadU16(&name_length) ||
|
||||
!table.ReadU16(&name_offset)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
// check platform & encoding, discard names with unknown values
|
||||
switch (rec.platformID) {
|
||||
case 0: // Unicode
|
||||
if (rec.encodingID > 6) {
|
||||
switch (rec.platform_id) {
|
||||
case 0: // Unicode
|
||||
if (rec.encoding_id > 6) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 1: // Macintosh
|
||||
if (rec.encoding_id > 32) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 2: // ISO
|
||||
if (rec.encoding_id > 2) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 3: // Windows: IDs 7 to 9 are "reserved"
|
||||
if (rec.encoding_id > 6 && rec.encoding_id != 10) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 4: // Custom (OTF Windows NT compatibility)
|
||||
if (rec.encoding_id > 255) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default: // unknown platform
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 1: // Macintosh
|
||||
if (rec.encodingID > 32) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 2: // ISO
|
||||
if (rec.encodingID > 2) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 3: // Windows: IDs 7 to 9 are "reserved"
|
||||
if (rec.encodingID > 6 && rec.encodingID != 10) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 4: // Custom (OTF Windows NT compatibility)
|
||||
if (rec.encodingID > 255) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default: // unknown platform
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size_t(stringOffset) + nameOffset + nameLength > length) {
|
||||
const unsigned name_end = static_cast<unsigned>(string_offset) +
|
||||
name_offset + name_length;
|
||||
if (name_end > length) {
|
||||
continue;
|
||||
}
|
||||
rec.text.resize(nameLength);
|
||||
rec.text.assign(stringBase + nameOffset, nameLength);
|
||||
rec.text.resize(name_length);
|
||||
rec.text.assign(string_base + name_offset, name_length);
|
||||
|
||||
if (rec.nameID == 6) {
|
||||
if (rec.name_id == 6) {
|
||||
// PostScript name: check that it is valid, if not then discard it
|
||||
if (rec.platformID == 1) {
|
||||
if (rec.platform_id == 1) {
|
||||
if (file->cff && !file->cff->name.empty()) {
|
||||
rec.text = file->cff->name;
|
||||
} else if (!check_ps_name_ascii(rec.text)) {
|
||||
} else if (!CheckPsNameAscii(rec.text)) {
|
||||
continue;
|
||||
}
|
||||
} else if (rec.platformID == 0 || rec.platformID == 3) {
|
||||
} else if (rec.platform_id == 0 || rec.platform_id == 3) {
|
||||
if (file->cff && !file->cff->name.empty()) {
|
||||
assign_to_utf16_be_from_ascii(rec.text, file->cff->name);
|
||||
} else if (!check_ps_name_utf16_be(rec.text)) {
|
||||
AssignToUtf16BeFromAscii(&rec.text, file->cff->name);
|
||||
} else if (!CheckPsNameUtf16Be(rec.text)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
if (!(prevRec < rec)) {
|
||||
sortRequired = true;
|
||||
}
|
||||
if ((i > 0) && !(prev_record < rec)) {
|
||||
OTS_WARNING("name records are not sorted.");
|
||||
sort_required = true;
|
||||
}
|
||||
|
||||
name->names.push_back(rec);
|
||||
prevRec = rec;
|
||||
prev_record = rec;
|
||||
}
|
||||
|
||||
if (format == 1) {
|
||||
// extended name table format with language tags
|
||||
uint16_t langTagCount;
|
||||
if (!table.ReadU16(&langTagCount)) {
|
||||
uint16_t lang_tag_count;
|
||||
if (!table.ReadU16(&lang_tag_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
for (unsigned int i = 0; i < langTagCount; ++i) {
|
||||
uint16_t tagLength, tagOffset;
|
||||
if (!table.ReadU16(&tagLength) || !table.ReadU16(&tagOffset)) {
|
||||
for (unsigned i = 0; i < lang_tag_count; ++i) {
|
||||
uint16_t tag_length = 0;
|
||||
uint16_t tag_offset = 0;
|
||||
if (!table.ReadU16(&tag_length) || !table.ReadU16(&tag_offset)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
if (size_t(stringOffset) + tagOffset + tagLength > length) {
|
||||
const unsigned tag_end = static_cast<unsigned>(string_offset) +
|
||||
tag_offset + tag_length;
|
||||
if (tag_end > length) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
std::string tag(stringBase + tagOffset, tagLength);
|
||||
name->langTags.push_back(tag);
|
||||
std::string tag(string_base + tag_offset, tag_length);
|
||||
name->lang_tags.push_back(tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (table.offset() > stringOffset) {
|
||||
if (table.offset() > string_offset) {
|
||||
// the string storage apparently overlapped the name/tag records;
|
||||
// consider this font to be badly broken
|
||||
return OTS_FAILURE();
|
||||
@ -192,8 +198,8 @@ bool ots_name_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
// 4 - full name
|
||||
// 5 - version
|
||||
// 6 - postscript name
|
||||
const unsigned int kStdNameCount = 7;
|
||||
const char* kStdNames[kStdNameCount] = {
|
||||
static const unsigned kStdNameCount = 7;
|
||||
static const char* kStdNames[kStdNameCount] = {
|
||||
NULL,
|
||||
"OTS derived font",
|
||||
"Unspecified",
|
||||
@ -211,112 +217,115 @@ bool ots_name_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
|
||||
// scan the names to check whether the required "standard" ones are present;
|
||||
// if not, we'll add our fixed versions here
|
||||
bool macName[kStdNameCount] = { 0 };
|
||||
bool winName[kStdNameCount] = { 0 };
|
||||
for (std::vector<NameRecord>::iterator nameIter = name->names.begin();
|
||||
nameIter != name->names.end(); nameIter++) {
|
||||
uint16_t id = nameIter->nameID;
|
||||
bool mac_name[kStdNameCount] = { 0 };
|
||||
bool win_name[kStdNameCount] = { 0 };
|
||||
for (std::vector<NameRecord>::iterator name_iter = name->names.begin();
|
||||
name_iter != name->names.end(); name_iter++) {
|
||||
const uint16_t id = name_iter->name_id;
|
||||
if (id >= kStdNameCount || kStdNames[id] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (nameIter->platformID == 1) {
|
||||
macName[id] = true;
|
||||
if (name_iter->platform_id == 1) {
|
||||
mac_name[id] = true;
|
||||
continue;
|
||||
}
|
||||
if (nameIter->platformID == 3) {
|
||||
winName[id] = true;
|
||||
if (name_iter->platform_id == 3) {
|
||||
win_name[id] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < kStdNameCount; ++i) {
|
||||
for (unsigned i = 0; i < kStdNameCount; ++i) {
|
||||
if (kStdNames[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!macName[i]) {
|
||||
NameRecord rec(1, 0, 0, i);
|
||||
if (!mac_name[i]) {
|
||||
NameRecord rec(1 /* platform_id */, 0 /* encoding_id */,
|
||||
0 /* language_id */ , i /* name_id */);
|
||||
rec.text.assign(kStdNames[i]);
|
||||
name->names.push_back(rec);
|
||||
sortRequired = true;
|
||||
sort_required = true;
|
||||
}
|
||||
if (!winName[i]) {
|
||||
NameRecord rec(3, 1, 1033, i);
|
||||
assign_to_utf16_be_from_ascii(rec.text, std::string(kStdNames[i]));
|
||||
if (!win_name[i]) {
|
||||
NameRecord rec(3 /* platform_id */, 1 /* encoding_id */,
|
||||
1033 /* language_id */ , i /* name_id */);
|
||||
AssignToUtf16BeFromAscii(&rec.text, std::string(kStdNames[i]));
|
||||
name->names.push_back(rec);
|
||||
sortRequired = true;
|
||||
sort_required = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sortRequired) {
|
||||
if (sort_required) {
|
||||
std::sort(name->names.begin(), name->names.end());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ots_name_should_serialise(OpenTypeFile *file) {
|
||||
bool ots_name_should_serialise(OpenTypeFile* file) {
|
||||
return file->name != NULL;
|
||||
}
|
||||
|
||||
bool ots_name_serialise(OTSStream *out, OpenTypeFile *file) {
|
||||
const OpenTypeNAME *name = file->name;
|
||||
bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) {
|
||||
const OpenTypeNAME* name = file->name;
|
||||
|
||||
uint16_t nameCount = name->names.size();
|
||||
uint16_t langTagCount = name->langTags.size();
|
||||
uint16_t name_count = name->names.size();
|
||||
uint16_t lang_tag_count = name->lang_tags.size();
|
||||
uint16_t format = 0;
|
||||
size_t stringOffset = 6 + nameCount * 12;
|
||||
size_t string_offset = 6 + name_count * 12;
|
||||
|
||||
if (name->langTags.size() > 0) {
|
||||
if (name->lang_tags.size() > 0) {
|
||||
// lang tags require a format-1 name table
|
||||
format = 1;
|
||||
stringOffset = 8 + nameCount * 12 + langTagCount * 4;
|
||||
string_offset += 2 + lang_tag_count * 4;
|
||||
}
|
||||
if (stringOffset > 0xffff) {
|
||||
if (string_offset > 0xffff) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
if (!out->WriteU16(format) ||
|
||||
!out->WriteU16(nameCount) ||
|
||||
!out->WriteU16(stringOffset)) {
|
||||
!out->WriteU16(name_count) ||
|
||||
!out->WriteU16(string_offset)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
std::string stringData;
|
||||
for (std::vector<NameRecord>::const_iterator nameIter = name->names.begin();
|
||||
nameIter != name->names.end(); nameIter++) {
|
||||
const NameRecord& rec = *nameIter;
|
||||
if (!out->WriteU16(rec.platformID) ||
|
||||
!out->WriteU16(rec.encodingID) ||
|
||||
!out->WriteU16(rec.languageID) ||
|
||||
!out->WriteU16(rec.nameID) ||
|
||||
std::string string_data;
|
||||
for (std::vector<NameRecord>::const_iterator name_iter = name->names.begin();
|
||||
name_iter != name->names.end(); name_iter++) {
|
||||
const NameRecord& rec = *name_iter;
|
||||
if (!out->WriteU16(rec.platform_id) ||
|
||||
!out->WriteU16(rec.encoding_id) ||
|
||||
!out->WriteU16(rec.language_id) ||
|
||||
!out->WriteU16(rec.name_id) ||
|
||||
!out->WriteU16(rec.text.size()) ||
|
||||
!out->WriteU16(stringData.size()) ) {
|
||||
!out->WriteU16(string_data.size()) ) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
stringData.append(rec.text);
|
||||
string_data.append(rec.text);
|
||||
}
|
||||
|
||||
if (format == 1) {
|
||||
if (!out->WriteU16(langTagCount)) {
|
||||
if (!out->WriteU16(lang_tag_count)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
for (std::vector<std::string>::const_iterator tagIter = name->langTags.begin();
|
||||
tagIter != name->langTags.end(); tagIter++) {
|
||||
if (!out->WriteU16(tagIter->size()) ||
|
||||
!out->WriteU16(stringData.size())) {
|
||||
for (std::vector<std::string>::const_iterator tag_iter =
|
||||
name->lang_tags.begin();
|
||||
tag_iter != name->lang_tags.end(); tag_iter++) {
|
||||
if (!out->WriteU16(tag_iter->size()) ||
|
||||
!out->WriteU16(string_data.size())) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
stringData.append(*tagIter);
|
||||
string_data.append(*tag_iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!out->Write(stringData.data(), stringData.size())) {
|
||||
if (!out->Write(string_data.data(), string_data.size())) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ots_name_free(OpenTypeFile *file) {
|
||||
void ots_name_free(OpenTypeFile* file) {
|
||||
delete file->name;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2011 Mozilla Foundation. All rights reserved.
|
||||
// Copyright (c) 2011 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.
|
||||
|
||||
@ -6,43 +6,46 @@
|
||||
#define OTS_NAME_H_
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ots.h"
|
||||
|
||||
namespace ots {
|
||||
|
||||
struct NameRecord {
|
||||
NameRecord()
|
||||
{ }
|
||||
NameRecord() {
|
||||
}
|
||||
|
||||
NameRecord(uint16_t p, uint16_t e, uint16_t l, uint16_t n)
|
||||
: platformID(p), encodingID(e), languageID(l), nameID(n)
|
||||
{ }
|
||||
NameRecord(uint16_t platform_id, uint16_t encoding_id,
|
||||
uint16_t language_id, uint16_t name_id)
|
||||
: platform_id(platform_id),
|
||||
encoding_id(encoding_id),
|
||||
language_id(language_id),
|
||||
name_id(name_id) {
|
||||
}
|
||||
|
||||
uint16_t platformID;
|
||||
uint16_t encodingID;
|
||||
uint16_t languageID;
|
||||
uint16_t nameID;
|
||||
uint16_t platform_id;
|
||||
uint16_t encoding_id;
|
||||
uint16_t language_id;
|
||||
uint16_t name_id;
|
||||
std::string text;
|
||||
|
||||
bool operator<(const NameRecord& rhs) const {
|
||||
if (platformID < rhs.platformID) return true;
|
||||
if (platformID > rhs.platformID) return false;
|
||||
if (encodingID < rhs.encodingID) return true;
|
||||
if (encodingID > rhs.encodingID) return false;
|
||||
if (languageID < rhs.languageID) return true;
|
||||
if (languageID > rhs.languageID) return false;
|
||||
if (nameID < rhs.nameID) return true;
|
||||
return false;
|
||||
if (platform_id < rhs.platform_id) return true;
|
||||
if (platform_id > rhs.platform_id) return false;
|
||||
if (encoding_id < rhs.encoding_id) return true;
|
||||
if (encoding_id > rhs.encoding_id) return false;
|
||||
if (language_id < rhs.language_id) return true;
|
||||
if (language_id > rhs.language_id) return false;
|
||||
return name_id < rhs.name_id;
|
||||
}
|
||||
};
|
||||
|
||||
struct OpenTypeNAME {
|
||||
std::vector<NameRecord> names;
|
||||
std::vector<std::string> langTags;
|
||||
std::vector<NameRecord> names;
|
||||
std::vector<std::string> lang_tags;
|
||||
};
|
||||
|
||||
} // namespace ots
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "os2.h"
|
||||
|
||||
#include "head.h"
|
||||
|
@ -392,9 +392,10 @@ bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output,
|
||||
std::vector<std::pair<uint32_t, uint8_t> > overlap_checker;
|
||||
for (unsigned i = 0; i < header->num_tables; ++i) {
|
||||
overlap_checker.push_back(
|
||||
std::make_pair(tables[i].offset, 1 /* start */));
|
||||
std::make_pair(tables[i].offset, static_cast<uint8_t>(1) /* start */));
|
||||
overlap_checker.push_back(
|
||||
std::make_pair(tables[i].offset + tables[i].length, 0 /* end */));
|
||||
std::make_pair(tables[i].offset + tables[i].length,
|
||||
static_cast<uint8_t>(0) /* end */));
|
||||
}
|
||||
std::sort(overlap_checker.begin(), overlap_checker.end());
|
||||
int overlap_count = 0;
|
||||
|
@ -5,7 +5,9 @@
|
||||
#ifndef OTS_H_
|
||||
#define OTS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
Loading…
Reference in New Issue
Block a user