summaryrefslogtreecommitdiffstats
path: root/gfx/ots/src/cmap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/ots/src/cmap.cc')
-rw-r--r--gfx/ots/src/cmap.cc342
1 files changed, 164 insertions, 178 deletions
diff --git a/gfx/ots/src/cmap.cc b/gfx/ots/src/cmap.cc
index 325f8e0d1..72c2a20fc 100644
--- a/gfx/ots/src/cmap.cc
+++ b/gfx/ots/src/cmap.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -15,8 +15,6 @@
// cmap - Character To Glyph Index Mapping Table
// http://www.microsoft.com/typography/otspec/cmap.htm
-#define TABLE_NAME "cmap"
-
namespace {
struct CMAPSubtableHeader {
@@ -56,8 +54,12 @@ const uint32_t kIVSStart = 0xE0100;
const uint32_t kIVSEnd = 0xE01EF;
const uint32_t kUVSUpperLimit = 0xFFFFFF;
+} // namespace
+
+namespace ots {
+
// Parses Format 4 tables
-bool ParseFormat4(ots::Font *font, int platform, int encoding,
+bool OpenTypeCMAP::ParseFormat4(int platform, int encoding,
const uint8_t *data, size_t length, uint16_t num_glyphs) {
ots::Buffer subtable(data, length);
@@ -65,20 +67,22 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
// whole thing and recompacting it, we validate it and include it verbatim
// in the output.
- if (!font->os2) {
- return OTS_FAILURE_MSG("Required OS/2 table missing");
+ OpenTypeOS2 *os2 = static_cast<OpenTypeOS2*>(
+ GetFont()->GetTypedTable(OTS_TAG_OS2));
+ if (!os2) {
+ return Error("Required OS/2 table missing");
}
if (!subtable.Skip(4)) {
- return OTS_FAILURE_MSG("Can't read 4 bytes at start of cmap format 4 subtable");
+ return Error("Can't read 4 bytes at start of cmap format 4 subtable");
}
uint16_t language = 0;
if (!subtable.ReadU16(&language)) {
- return OTS_FAILURE_MSG("Can't read language");
+ return Error("Can't read language");
}
if (language) {
// Platform ID 3 (windows) subtables should have language '0'.
- return OTS_FAILURE_MSG("Languages should be 0 (%d)", language);
+ return Error("Languages should be 0 (%d)", language);
}
uint16_t segcountx2, search_range, entry_selector, range_shift;
@@ -87,16 +91,16 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
!subtable.ReadU16(&search_range) ||
!subtable.ReadU16(&entry_selector) ||
!subtable.ReadU16(&range_shift)) {
- return OTS_FAILURE_MSG("Failed to read subcmap structure");
+ return Error("Failed to read subcmap structure");
}
if (segcountx2 & 1 || search_range & 1) {
- return OTS_FAILURE_MSG("Bad subcmap structure");
+ return Error("Bad subcmap structure");
}
const uint16_t segcount = segcountx2 >> 1;
// There must be at least one segment according the spec.
if (segcount < 1) {
- return OTS_FAILURE_MSG("Segcount < 1 (%d)", segcount);
+ return Error("Segcount < 1 (%d)", segcount);
}
// log2segcount is the maximal x s.t. 2^x < segcount
@@ -107,48 +111,48 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
const uint16_t expected_search_range = 2 * 1u << log2segcount;
if (expected_search_range != search_range) {
- return OTS_FAILURE_MSG("expected search range != search range (%d != %d)", expected_search_range, search_range);
+ return Error("expected search range != search range (%d != %d)", expected_search_range, search_range);
}
if (entry_selector != log2segcount) {
- return OTS_FAILURE_MSG("entry selector != log2(segement count) (%d != %d)", entry_selector, log2segcount);
+ return Error("entry selector != log2(segement count) (%d != %d)", entry_selector, log2segcount);
}
const uint16_t expected_range_shift = segcountx2 - search_range;
if (range_shift != expected_range_shift) {
- return OTS_FAILURE_MSG("unexpected range shift (%d != %d)", range_shift, expected_range_shift);
+ return Error("unexpected range shift (%d != %d)", range_shift, expected_range_shift);
}
std::vector<Subtable314Range> ranges(segcount);
for (unsigned i = 0; i < segcount; ++i) {
if (!subtable.ReadU16(&ranges[i].end_range)) {
- return OTS_FAILURE_MSG("Failed to read segment %d", i);
+ return Error("Failed to read segment %d", i);
}
}
uint16_t padding;
if (!subtable.ReadU16(&padding)) {
- return OTS_FAILURE_MSG("Failed to read cmap subtable segment padding");
+ return Error("Failed to read cmap subtable segment padding");
}
if (padding) {
- return OTS_FAILURE_MSG("Non zero cmap subtable segment padding (%d)", padding);
+ return Error("Non zero cmap subtable segment padding (%d)", padding);
}
for (unsigned i = 0; i < segcount; ++i) {
if (!subtable.ReadU16(&ranges[i].start_range)) {
- return OTS_FAILURE_MSG("Failed to read segment start range %d", i);
+ return Error("Failed to read segment start range %d", i);
}
}
for (unsigned i = 0; i < segcount; ++i) {
if (!subtable.ReadS16(&ranges[i].id_delta)) {
- return OTS_FAILURE_MSG("Failed to read segment delta %d", i);
+ return Error("Failed to read segment delta %d", i);
}
}
for (unsigned i = 0; i < segcount; ++i) {
ranges[i].id_range_offset_offset = subtable.offset();
if (!subtable.ReadU16(&ranges[i].id_range_offset)) {
- return OTS_FAILURE_MSG("Failed to read segment range offset %d", i);
+ return Error("Failed to read segment range offset %d", i);
}
if (ranges[i].id_range_offset & 1) {
@@ -156,12 +160,12 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
// for 0xFFFF-0xFFFF range.
// (e.g., many fonts in http://www.princexml.com/fonts/)
if (i == segcount - 1u) {
- OTS_WARNING("bad id_range_offset");
+ Warning("bad id_range_offset");
ranges[i].id_range_offset = 0;
// The id_range_offset value in the transcoded font will not change
// since this table is not actually "transcoded" yet.
} else {
- return OTS_FAILURE_MSG("Bad segment offset (%d)", ranges[i].id_range_offset);
+ return Error("Bad segment offset (%d)", ranges[i].id_range_offset);
}
}
}
@@ -176,36 +180,36 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
(ranges[i].end_range == 0xffff)) {
// Some fonts (e.g., Germania.ttf) have multiple 0xffff terminators.
// We'll accept them as an exception.
- OTS_WARNING("multiple 0xffff terminators found");
+ Warning("multiple 0xffff terminators found");
continue;
}
// Note: some Linux fonts (e.g., LucidaSansOblique.ttf, bsmi00lp.ttf) have
// unsorted table...
if (ranges[i].end_range <= ranges[i - 1].end_range) {
- return OTS_FAILURE_MSG("Out of order end range (%d <= %d)", ranges[i].end_range, ranges[i-1].end_range);
+ return Error("Out of order end range (%d <= %d)", ranges[i].end_range, ranges[i-1].end_range);
}
if (ranges[i].start_range <= ranges[i - 1].end_range) {
- return OTS_FAILURE_MSG("out of order start range (%d <= %d)", ranges[i].start_range, ranges[i-1].end_range);
+ return Error("out of order start range (%d <= %d)", ranges[i].start_range, ranges[i-1].end_range);
}
// On many fonts, the value of {first, last}_char_index are incorrect.
// Fix them.
- if (font->os2->first_char_index != 0xFFFF &&
+ if (os2->table.first_char_index != 0xFFFF &&
ranges[i].start_range != 0xFFFF &&
- font->os2->first_char_index > ranges[i].start_range) {
- font->os2->first_char_index = ranges[i].start_range;
+ os2->table.first_char_index > ranges[i].start_range) {
+ os2->table.first_char_index = ranges[i].start_range;
}
- if (font->os2->last_char_index != 0xFFFF &&
+ if (os2->table.last_char_index != 0xFFFF &&
ranges[i].end_range != 0xFFFF &&
- font->os2->last_char_index < ranges[i].end_range) {
- font->os2->last_char_index = ranges[i].end_range;
+ os2->table.last_char_index < ranges[i].end_range) {
+ os2->table.last_char_index = ranges[i].end_range;
}
}
// The last range must end at 0xffff
if (ranges[segcount - 1].start_range != 0xffff || ranges[segcount - 1].end_range != 0xffff) {
- return OTS_FAILURE_MSG("Final segment start and end must be 0xFFFF (0x%04X-0x%04X)",
+ return Error("Final segment start and end must be 0xFFFF (0x%04X-0x%04X)",
ranges[segcount - 1].start_range, ranges[segcount - 1].end_range);
}
@@ -219,7 +223,7 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
// this is explictly allowed to overflow in the spec
const uint16_t glyph = code_point + ranges[i].id_delta;
if (glyph >= num_glyphs) {
- return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", glyph, num_glyphs - 1);
+ return Error("Range glyph reference too high (%d > %d)", glyph, num_glyphs - 1);
}
} else {
const uint16_t range_delta = code_point - ranges[i].start_range;
@@ -230,13 +234,13 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
range_delta * 2;
// We need to be able to access a 16-bit value from this offset
if (glyph_id_offset + 1 >= length) {
- return OTS_FAILURE_MSG("bad glyph id offset (%d > %ld)", glyph_id_offset, length);
+ return Error("bad glyph id offset (%d > %ld)", glyph_id_offset, length);
}
uint16_t glyph;
std::memcpy(&glyph, data + glyph_id_offset, 2);
- glyph = ntohs(glyph);
+ glyph = ots_ntohs(glyph);
if (glyph >= num_glyphs) {
- return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", glyph, num_glyphs - 1);
+ return Error("Range glyph reference too high (%d > %d)", glyph, num_glyphs - 1);
}
}
}
@@ -245,85 +249,85 @@ bool ParseFormat4(ots::Font *font, int platform, int encoding,
// We accept the table.
// TODO(yusukes): transcode the subtable.
if (platform == 3 && encoding == 0) {
- font->cmap->subtable_3_0_4_data = data;
- font->cmap->subtable_3_0_4_length = length;
+ this->subtable_3_0_4_data = data;
+ this->subtable_3_0_4_length = length;
} else if (platform == 3 && encoding == 1) {
- font->cmap->subtable_3_1_4_data = data;
- font->cmap->subtable_3_1_4_length = length;
+ this->subtable_3_1_4_data = data;
+ this->subtable_3_1_4_length = length;
} else if (platform == 0 && encoding == 3) {
- font->cmap->subtable_0_3_4_data = data;
- font->cmap->subtable_0_3_4_length = length;
+ this->subtable_0_3_4_data = data;
+ this->subtable_0_3_4_length = length;
} else {
- return OTS_FAILURE_MSG("Unknown cmap subtable type (platform=%d, encoding=%d)", platform, encoding);
+ return Error("Unknown cmap subtable type (platform=%d, encoding=%d)", platform, encoding);
}
return true;
}
-bool Parse31012(ots::Font *font,
- const uint8_t *data, size_t length, uint16_t num_glyphs) {
+bool OpenTypeCMAP::Parse31012(const uint8_t *data, size_t length,
+ uint16_t num_glyphs) {
ots::Buffer subtable(data, length);
// Format 12 tables are simple. We parse these and fully serialise them
// later.
if (!subtable.Skip(8)) {
- return OTS_FAILURE_MSG("failed to skip the first 8 bytes of format 12 subtable");
+ return Error("failed to skip the first 8 bytes of format 12 subtable");
}
uint32_t language = 0;
if (!subtable.ReadU32(&language)) {
- return OTS_FAILURE_MSG("can't read format 12 subtable language");
+ return Error("can't read format 12 subtable language");
}
if (language) {
- return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", language);
+ return Error("format 12 subtable language should be zero (%d)", language);
}
uint32_t num_groups = 0;
if (!subtable.ReadU32(&num_groups)) {
- return OTS_FAILURE_MSG("can't read number of format 12 subtable groups");
+ return Error("can't read number of format 12 subtable groups");
}
if (num_groups == 0 || subtable.remaining() / 12 < num_groups) {
- return OTS_FAILURE_MSG("Bad format 12 subtable group count %d", num_groups);
+ return Error("Bad format 12 subtable group count %d", num_groups);
}
std::vector<ots::OpenTypeCMAPSubtableRange> &groups
- = font->cmap->subtable_3_10_12;
+ = this->subtable_3_10_12;
groups.resize(num_groups);
for (unsigned i = 0; i < num_groups; ++i) {
if (!subtable.ReadU32(&groups[i].start_range) ||
!subtable.ReadU32(&groups[i].end_range) ||
!subtable.ReadU32(&groups[i].start_glyph_id)) {
- return OTS_FAILURE_MSG("can't read format 12 subtable group");
+ return Error("can't read format 12 subtable group");
}
if (groups[i].start_range > kUnicodeUpperLimit ||
groups[i].end_range > kUnicodeUpperLimit ||
groups[i].start_glyph_id > 0xFFFF) {
- return OTS_FAILURE_MSG("bad format 12 subtable group (startCharCode=0x%4X, endCharCode=0x%4X, startGlyphID=%d)",
+ return Error("bad format 12 subtable group (startCharCode=0x%4X, endCharCode=0x%4X, startGlyphID=%d)",
groups[i].start_range, groups[i].end_range, groups[i].start_glyph_id);
}
// We assert that the glyph value is within range. Because of the range
// limits, above, we don't need to worry about overflow.
if (groups[i].end_range < groups[i].start_range) {
- return OTS_FAILURE_MSG("format 12 subtable group endCharCode before startCharCode (0x%4X < 0x%4X)",
+ return Error("format 12 subtable group endCharCode before startCharCode (0x%4X < 0x%4X)",
groups[i].end_range, groups[i].start_range);
}
if ((groups[i].end_range - groups[i].start_range) +
groups[i].start_glyph_id > num_glyphs) {
- return OTS_FAILURE_MSG("bad format 12 subtable group startGlyphID (%d)", groups[i].start_glyph_id);
+ return Error("bad format 12 subtable group startGlyphID (%d)", groups[i].start_glyph_id);
}
}
// the groups must be sorted by start code and may not overlap
for (unsigned i = 1; i < num_groups; ++i) {
if (groups[i].start_range <= groups[i - 1].start_range) {
- return OTS_FAILURE_MSG("out of order format 12 subtable group (startCharCode=0x%4X <= startCharCode=0x%4X of previous group)",
+ return Error("out of order format 12 subtable group (startCharCode=0x%4X <= startCharCode=0x%4X of previous group)",
groups[i].start_range, groups[i-1].start_range);
}
if (groups[i].start_range <= groups[i - 1].end_range) {
- return OTS_FAILURE_MSG("overlapping format 12 subtable groups (startCharCode=0x%4X <= endCharCode=0x%4X of previous group)",
+ return Error("overlapping format 12 subtable groups (startCharCode=0x%4X <= endCharCode=0x%4X of previous group)",
groups[i].start_range, groups[i-1].end_range);
}
}
@@ -331,44 +335,43 @@ bool Parse31012(ots::Font *font,
return true;
}
-bool Parse31013(ots::Font *font,
- const uint8_t *data, size_t length, uint16_t num_glyphs) {
+bool OpenTypeCMAP::Parse31013(const uint8_t *data, size_t length,
+ uint16_t num_glyphs) {
ots::Buffer subtable(data, length);
// Format 13 tables are simple. We parse these and fully serialise them
// later.
if (!subtable.Skip(8)) {
- return OTS_FAILURE_MSG("Bad cmap subtable length");
+ return Error("Bad cmap subtable length");
}
uint32_t language = 0;
if (!subtable.ReadU32(&language)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable language");
+ return Error("Can't read cmap subtable language");
}
if (language) {
- return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", language);
+ return Error("Cmap subtable language should be zero but is %d", language);
}
uint32_t num_groups = 0;
if (!subtable.ReadU32(&num_groups)) {
- return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable");
+ return Error("Can't read number of groups in a cmap subtable");
}
// We limit the number of groups in the same way as in 3.10.12 tables. See
// the comment there in
if (num_groups == 0 || subtable.remaining() / 12 < num_groups) {
- return OTS_FAILURE_MSG("Bad format 13 subtable group count %d", num_groups);
+ return Error("Bad format 13 subtable group count %d", num_groups);
}
- std::vector<ots::OpenTypeCMAPSubtableRange> &groups
- = font->cmap->subtable_3_10_13;
+ std::vector<ots::OpenTypeCMAPSubtableRange> &groups = this->subtable_3_10_13;
groups.resize(num_groups);
for (unsigned i = 0; i < num_groups; ++i) {
if (!subtable.ReadU32(&groups[i].start_range) ||
!subtable.ReadU32(&groups[i].end_range) ||
!subtable.ReadU32(&groups[i].start_glyph_id)) {
- return OTS_FAILURE_MSG("Can't read subrange structure in a cmap subtable");
+ return Error("Can't read subrange structure in a cmap subtable");
}
// We conservatively limit all of the values to protect some parsers from
@@ -376,29 +379,29 @@ bool Parse31013(ots::Font *font,
if (groups[i].start_range > kUnicodeUpperLimit ||
groups[i].end_range > kUnicodeUpperLimit ||
groups[i].start_glyph_id > 0xFFFF) {
- return OTS_FAILURE_MSG("Bad subrange with start_range=%d, end_range=%d, start_glyph_id=%d", groups[i].start_range, groups[i].end_range, groups[i].start_glyph_id);
+ return Error("Bad subrange with start_range=%d, end_range=%d, start_glyph_id=%d", groups[i].start_range, groups[i].end_range, groups[i].start_glyph_id);
}
if (groups[i].start_glyph_id >= num_glyphs) {
- return OTS_FAILURE_MSG("Subrange starting glyph id too high (%d > %d)", groups[i].start_glyph_id, num_glyphs);
+ return Error("Subrange starting glyph id too high (%d > %d)", groups[i].start_glyph_id, num_glyphs);
}
}
// the groups must be sorted by start code and may not overlap
for (unsigned i = 1; i < num_groups; ++i) {
if (groups[i].start_range <= groups[i - 1].start_range) {
- return OTS_FAILURE_MSG("Overlapping subrange starts (%d >= %d)", groups[i]. start_range, groups[i-1].start_range);
+ return Error("Overlapping subrange starts (%d >= %d)", groups[i]. start_range, groups[i-1].start_range);
}
if (groups[i].start_range <= groups[i - 1].end_range) {
- return OTS_FAILURE_MSG("Overlapping subranges (%d <= %d)", groups[i].start_range, groups[i-1].end_range);
+ return Error("Overlapping subranges (%d <= %d)", groups[i].start_range, groups[i-1].end_range);
}
}
return true;
}
-bool Parse0514(ots::Font *font,
- const uint8_t *data, size_t length, uint16_t num_glyphs) {
+bool OpenTypeCMAP::Parse0514(const uint8_t *data, size_t length,
+ uint16_t num_glyphs) {
// Unicode Variation Selector table
ots::Buffer subtable(data, length);
@@ -407,26 +410,26 @@ bool Parse0514(ots::Font *font,
// Skip format (USHORT) and length (ULONG)
if (!subtable.Skip(6)) {
- return OTS_FAILURE_MSG("Can't read start of cmap subtable");
+ return Error("Can't read start of cmap subtable");
}
uint32_t num_records = 0;
if (!subtable.ReadU32(&num_records)) {
- return OTS_FAILURE_MSG("Can't read number of records in cmap subtable");
+ return Error("Can't read number of records in cmap subtable");
}
if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) {
- return OTS_FAILURE_MSG("Bad format 14 subtable records count %d", num_records);
+ return Error("Bad format 14 subtable records count %d", num_records);
}
std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records
- = font->cmap->subtable_0_5_14;
+ = this->subtable_0_5_14;
records.resize(num_records);
for (unsigned i = 0; i < num_records; ++i) {
if (!subtable.ReadU24(&records[i].var_selector) ||
!subtable.ReadU32(&records[i].default_offset) ||
!subtable.ReadU32(&records[i].non_default_offset)) {
- return OTS_FAILURE_MSG("Can't read record structure of record %d in cmap subtale", i);
+ return Error("Can't read record structure of record %d in cmap subtale", i);
}
// Checks the value of variation selector
if (!((records[i].var_selector >= kMongolianVSStart &&
@@ -435,24 +438,24 @@ bool Parse0514(ots::Font *font,
records[i].var_selector <= kVSEnd) ||
(records[i].var_selector >= kIVSStart &&
records[i].var_selector <= kIVSEnd))) {
- return OTS_FAILURE_MSG("Bad record variation selector (%04X) in record %i", records[i].var_selector, i);
+ return Error("Bad record variation selector (%04X) in record %i", records[i].var_selector, i);
}
if (i > 0 &&
records[i-1].var_selector >= records[i].var_selector) {
- return OTS_FAILURE_MSG("Out of order variation selector (%04X >= %04X) in record %d", records[i-1].var_selector, records[i].var_selector, i);
+ return Error("Out of order variation selector (%04X >= %04X) in record %d", records[i-1].var_selector, records[i].var_selector, i);
}
// Checks offsets
if (!records[i].default_offset && !records[i].non_default_offset) {
- return OTS_FAILURE_MSG("No default aoffset in variation selector record %d", i);
+ return Error("No default aoffset in variation selector record %d", i);
}
if (records[i].default_offset &&
records[i].default_offset >= length) {
- return OTS_FAILURE_MSG("Default offset too high (%d >= %ld) in record %d", records[i].default_offset, length, i);
+ return Error("Default offset too high (%d >= %ld) in record %d", records[i].default_offset, length, i);
}
if (records[i].non_default_offset &&
records[i].non_default_offset >= length) {
- return OTS_FAILURE_MSG("Non default offset too high (%d >= %ld) in record %d", records[i].non_default_offset, length, i);
+ return Error("Non default offset too high (%d >= %ld) in record %d", records[i].non_default_offset, length, i);
}
}
@@ -462,10 +465,10 @@ bool Parse0514(ots::Font *font,
subtable.set_offset(records[i].default_offset);
uint32_t num_ranges = 0;
if (!subtable.ReadU32(&num_ranges)) {
- return OTS_FAILURE_MSG("Can't read number of ranges in record %d", i);
+ return Error("Can't read number of ranges in record %d", i);
}
if (num_ranges == 0 || subtable.remaining() / 4 < num_ranges) {
- return OTS_FAILURE_MSG("Bad number of ranges (%d) in record %d", num_ranges, i);
+ return Error("Bad number of ranges (%d) in record %d", num_ranges, i);
}
uint32_t last_unicode_value = 0;
@@ -476,7 +479,7 @@ bool Parse0514(ots::Font *font,
for (unsigned j = 0; j < num_ranges; ++j) {
if (!subtable.ReadU24(&ranges[j].unicode_value) ||
!subtable.ReadU8(&ranges[j].additional_count)) {
- return OTS_FAILURE_MSG("Can't read range info in variation selector record %d", i);
+ return Error("Can't read range info in variation selector record %d", i);
}
const uint32_t check_value =
ranges[j].unicode_value + ranges[j].additional_count;
@@ -485,7 +488,7 @@ bool Parse0514(ots::Font *font,
check_value > kUVSUpperLimit ||
(last_unicode_value &&
ranges[j].unicode_value <= last_unicode_value)) {
- return OTS_FAILURE_MSG("Bad Unicode value *%04X) in variation selector range %d record %d", ranges[j].unicode_value, j, i);
+ return Error("Bad Unicode value *%04X) in variation selector range %d record %d", ranges[j].unicode_value, j, i);
}
last_unicode_value = check_value;
}
@@ -496,10 +499,10 @@ bool Parse0514(ots::Font *font,
subtable.set_offset(records[i].non_default_offset);
uint32_t num_mappings = 0;
if (!subtable.ReadU32(&num_mappings)) {
- return OTS_FAILURE_MSG("Can't read number of mappings in variation selector record %d", i);
+ return Error("Can't read number of mappings in variation selector record %d", i);
}
if (num_mappings == 0 || subtable.remaining() / 5 < num_mappings) {
- return OTS_FAILURE_MSG("Bad number of mappings (%d) in variation selector record %d", num_mappings, i);
+ return Error("Bad number of mappings (%d) in variation selector record %d", num_mappings, i);
}
uint32_t last_unicode_value = 0;
@@ -510,14 +513,14 @@ bool Parse0514(ots::Font *font,
for (unsigned j = 0; j < num_mappings; ++j) {
if (!subtable.ReadU24(&mappings[j].unicode_value) ||
!subtable.ReadU16(&mappings[j].glyph_id)) {
- return OTS_FAILURE_MSG("Can't read mapping %d in variation selector record %d", j, i);
+ return Error("Can't read mapping %d in variation selector record %d", j, i);
}
if (mappings[j].glyph_id == 0 ||
mappings[j].unicode_value == 0 ||
mappings[j].unicode_value > kUnicodeUpperLimit ||
(last_unicode_value &&
mappings[j].unicode_value <= last_unicode_value)) {
- return OTS_FAILURE_MSG("Bad mapping (%04X -> %d) in mapping %d of variation selector %d", mappings[j].unicode_value, mappings[j].glyph_id, j, i);
+ return Error("Bad mapping (%04X -> %d) in mapping %d of variation selector %d", mappings[j].unicode_value, mappings[j].glyph_id, j, i);
}
last_unicode_value = mappings[j].unicode_value;
}
@@ -525,60 +528,55 @@ bool Parse0514(ots::Font *font,
}
if (subtable.offset() != length) {
- return OTS_FAILURE_MSG("Bad subtable offset (%ld != %ld)", subtable.offset(), length);
+ return Error("Bad subtable offset (%ld != %ld)", subtable.offset(), length);
}
- font->cmap->subtable_0_5_14_length = subtable.offset();
+ this->subtable_0_5_14_length = subtable.offset();
return true;
}
-bool Parse100(ots::Font *font, const uint8_t *data, size_t length) {
+bool OpenTypeCMAP::Parse100(const uint8_t *data, size_t length) {
// Mac Roman table
ots::Buffer subtable(data, length);
if (!subtable.Skip(4)) {
- return OTS_FAILURE_MSG("Bad cmap subtable");
+ return Error("Bad cmap subtable");
}
uint16_t language = 0;
if (!subtable.ReadU16(&language)) {
- return OTS_FAILURE_MSG("Can't read language in cmap subtable");
+ return Error("Can't read language in cmap subtable");
}
if (language) {
// simsun.ttf has non-zero language id.
- OTS_WARNING("language id should be zero: %u", language);
+ Warning("language id should be zero: %u", language);
}
- font->cmap->subtable_1_0_0.reserve(kFormat0ArraySize);
+ this->subtable_1_0_0.reserve(kFormat0ArraySize);
for (size_t i = 0; i < kFormat0ArraySize; ++i) {
uint8_t glyph_id = 0;
if (!subtable.ReadU8(&glyph_id)) {
- return OTS_FAILURE_MSG("Can't read glyph id at array[%ld] in cmap subtable", i);
+ return Error("Can't read glyph id at array[%ld] in cmap subtable", i);
}
- font->cmap->subtable_1_0_0.push_back(glyph_id);
+ this->subtable_1_0_0.push_back(glyph_id);
}
return true;
}
-} // namespace
-
-namespace ots {
-
-bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
+bool OpenTypeCMAP::Parse(const uint8_t *data, size_t length) {
Buffer table(data, length);
- font->cmap = new OpenTypeCMAP;
uint16_t version = 0;
uint16_t num_tables = 0;
if (!table.ReadU16(&version) ||
!table.ReadU16(&num_tables)) {
- return OTS_FAILURE_MSG("Can't read structure of cmap");
+ return Error("Can't read structure of cmap");
}
if (version != 0) {
- return OTS_FAILURE_MSG("Non zero cmap version (%d)", version);
+ return Error("Non zero cmap version (%d)", version);
}
if (!num_tables) {
- return OTS_FAILURE_MSG("No subtables in cmap!");
+ return Error("No subtables in cmap!");
}
std::vector<CMAPSubtableHeader> subtable_headers;
@@ -591,7 +589,7 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
if (!table.ReadU16(&subt.platform) ||
!table.ReadU16(&subt.encoding) ||
!table.ReadU32(&subt.offset)) {
- return OTS_FAILURE_MSG("Can't read subtable information cmap subtable %d", i);
+ return Error("Can't read subtable information cmap subtable %d", i);
}
subtable_headers.push_back(subt);
@@ -602,11 +600,11 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
// make sure that all the offsets are valid.
for (unsigned i = 0; i < num_tables; ++i) {
if (subtable_headers[i].offset > 1024 * 1024 * 1024) {
- return OTS_FAILURE_MSG("Bad subtable offset in cmap subtable %d", i);
+ return Error("Bad subtable offset in cmap subtable %d", i);
}
if (subtable_headers[i].offset < data_offset ||
subtable_headers[i].offset >= length) {
- return OTS_FAILURE_MSG("Bad subtable offset (%d) in cmap subtable %d", subtable_headers[i].offset, i);
+ return Error("Bad subtable offset (%d) in cmap subtable %d", subtable_headers[i].offset, i);
}
}
@@ -615,7 +613,7 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
for (unsigned i = 0; i < num_tables; ++i) {
table.set_offset(subtable_headers[i].offset);
if (!table.ReadU16(&subtable_headers[i].format)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable header format %d", i);
+ return Error("Can't read cmap subtable header format %d", i);
}
uint16_t len = 0;
@@ -624,10 +622,10 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
case 0:
case 4:
if (!table.ReadU16(&len)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable %d length", i);
+ return Error("Can't read cmap subtable %d length", i);
}
if (!table.ReadU16(&lang)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable %d language", i);
+ return Error("Can't read cmap subtable %d language", i);
}
subtable_headers[i].length = len;
subtable_headers[i].language = lang;
@@ -635,18 +633,18 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
case 12:
case 13:
if (!table.Skip(2)) {
- return OTS_FAILURE_MSG("Bad cmap subtable %d structure", i);
+ return Error("Bad cmap subtable %d structure", i);
}
if (!table.ReadU32(&subtable_headers[i].length)) {
- return OTS_FAILURE_MSG("Can read cmap subtable %d length", i);
+ return Error("Can read cmap subtable %d length", i);
}
if (!table.ReadU32(&subtable_headers[i].language)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable %d language", i);
+ return Error("Can't read cmap subtable %d language", i);
}
break;
case 14:
if (!table.ReadU32(&subtable_headers[i].length)) {
- return OTS_FAILURE_MSG("Can't read cmap subtable %d length", i);
+ return Error("Can't read cmap subtable %d length", i);
}
subtable_headers[i].language = 0;
break;
@@ -664,7 +662,7 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
(subtable_headers[i - 1].encoding > subtable_headers[i].encoding ||
(subtable_headers[i - 1].encoding == subtable_headers[i].encoding &&
subtable_headers[i - 1].language > subtable_headers[i].language))))
- OTS_WARNING("subtable %d with platform ID %d, encoding ID %d, language ID %d "
+ Warning("subtable %d with platform ID %d, encoding ID %d, language ID %d "
"following subtable with platform ID %d, encoding ID %d, language ID %d",
i,
subtable_headers[i].platform,
@@ -679,14 +677,14 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
for (unsigned i = 0; i < num_tables; ++i) {
if (!subtable_headers[i].length) continue;
if (subtable_headers[i].length > 1024 * 1024 * 1024) {
- return OTS_FAILURE_MSG("Bad cmap subtable %d length", i);
+ return Error("Bad cmap subtable %d length", i);
}
// We know that both the offset and length are < 1GB, so the following
// addition doesn't overflow
const uint32_t end_byte
= subtable_headers[i].offset + subtable_headers[i].length;
if (end_byte > length) {
- return OTS_FAILURE_MSG("Over long cmap subtable %d @ %d for %d", i, subtable_headers[i].offset, subtable_headers[i].length);
+ return Error("Over long cmap subtable %d @ %d for %d", i, subtable_headers[i].offset, subtable_headers[i].length);
}
}
@@ -714,16 +712,18 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
for (unsigned i = 0; i < overlap_checker.size(); ++i) {
overlap_count += (overlap_checker[i].second ? 1 : -1);
if (overlap_count > 1) {
- return OTS_FAILURE_MSG("Excessive overlap count %d", overlap_count);
+ return Error("Excessive overlap count %d", overlap_count);
}
}
// we grab the number of glyphs in the file from the maxp table to make sure
// that the character map isn't referencing anything beyound this range.
- if (!font->maxp) {
- return OTS_FAILURE_MSG("No maxp table in font! Needed by cmap.");
+ OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>(
+ GetFont()->GetTypedTable(OTS_TAG_MAXP));
+ if (!maxp) {
+ return Error("No maxp table in font! Needed by cmap.");
}
- const uint16_t num_glyphs = font->maxp->num_glyphs;
+ const uint16_t num_glyphs = maxp->num_glyphs;
// We only support a subset of the possible character map tables. Microsoft
// 'strongly recommends' that everyone supports the Unicode BMP table with
@@ -760,29 +760,30 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
// table actually points to MS symbol data and thus should be parsed as
// 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be
// recovered in ots_cmap_serialise().
- if (!ParseFormat4(font, 3, 1, data + subtable_headers[i].offset,
+ if (!ParseFormat4(3, 1, data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
- return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i);
+ return Error("Failed to parse format 4 cmap subtable %d", i);
}
} else if ((subtable_headers[i].encoding == 3) &&
(subtable_headers[i].format == 4)) {
// parse and output the 0-3-4 table as 0-3-4 table.
- if (!ParseFormat4(font, 0, 3, data + subtable_headers[i].offset,
+ if (!ParseFormat4(0, 3, data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
- return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i);
+ return Error("Failed to parse format 4 cmap subtable %d", i);
}
- } else if ((subtable_headers[i].encoding == 3) &&
+ } else if ((subtable_headers[i].encoding == 3 ||
+ subtable_headers[i].encoding == 4) &&
(subtable_headers[i].format == 12)) {
- // parse and output the 0-3-12 table as 3-10-12 table.
- if (!Parse31012(font, data + subtable_headers[i].offset,
+ // parse and output the 0-3-12 or 0-4-12 tables as 3-10-12 table.
+ if (!Parse31012(data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
- return OTS_FAILURE_MSG("Failed to parse format 12 cmap subtable %d", i);
+ return Error("Failed to parse format 12 cmap subtable %d", i);
}
} else if ((subtable_headers[i].encoding == 5) &&
(subtable_headers[i].format == 14)) {
- if (!Parse0514(font, data + subtable_headers[i].offset,
+ if (!Parse0514(data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
- return OTS_FAILURE_MSG("Failed to parse format 14 cmap subtable %d", i);
+ return Error("Failed to parse format 14 cmap subtable %d", i);
}
}
} else if (subtable_headers[i].platform == 1) {
@@ -791,7 +792,7 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
if ((subtable_headers[i].encoding == 0) &&
(subtable_headers[i].format == 0)) {
// parse and output the 1-0-0 table.
- if (!Parse100(font, data + subtable_headers[i].offset,
+ if (!Parse100(data + subtable_headers[i].offset,
subtable_headers[i].length)) {
return OTS_FAILURE();
}
@@ -804,7 +805,7 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
case 1:
if (subtable_headers[i].format == 4) {
// parse 3-0-4 or 3-1-4 table.
- if (!ParseFormat4(font, subtable_headers[i].platform,
+ if (!ParseFormat4(subtable_headers[i].platform,
subtable_headers[i].encoding,
data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
@@ -814,14 +815,14 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
break;
case 10:
if (subtable_headers[i].format == 12) {
- font->cmap->subtable_3_10_12.clear();
- if (!Parse31012(font, data + subtable_headers[i].offset,
+ this->subtable_3_10_12.clear();
+ if (!Parse31012(data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
return OTS_FAILURE();
}
} else if (subtable_headers[i].format == 13) {
- font->cmap->subtable_3_10_13.clear();
- if (!Parse31013(font, data + subtable_headers[i].offset,
+ this->subtable_3_10_13.clear();
+ if (!Parse31013(data + subtable_headers[i].offset,
subtable_headers[i].length, num_glyphs)) {
return OTS_FAILURE();
}
@@ -834,20 +835,16 @@ bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
return true;
}
-bool ots_cmap_should_serialise(Font *font) {
- return font->cmap != NULL;
-}
-
-bool ots_cmap_serialise(OTSStream *out, Font *font) {
- const bool have_034 = font->cmap->subtable_0_3_4_data != NULL;
- const bool have_0514 = font->cmap->subtable_0_5_14.size() != 0;
- const bool have_100 = font->cmap->subtable_1_0_0.size() != 0;
- const bool have_304 = font->cmap->subtable_3_0_4_data != NULL;
+bool OpenTypeCMAP::Serialize(OTSStream *out) {
+ const bool have_034 = this->subtable_0_3_4_data != NULL;
+ const bool have_0514 = this->subtable_0_5_14.size() != 0;
+ const bool have_100 = this->subtable_1_0_0.size() != 0;
+ const bool have_304 = this->subtable_3_0_4_data != NULL;
// MS Symbol and MS Unicode tables should not co-exist.
// See the comment above in 0-0-4 parser.
- const bool have_314 = (!have_304) && font->cmap->subtable_3_1_4_data;
- const bool have_31012 = font->cmap->subtable_3_10_12.size() != 0;
- const bool have_31013 = font->cmap->subtable_3_10_13.size() != 0;
+ const bool have_314 = (!have_304) && this->subtable_3_1_4_data;
+ const bool have_31012 = this->subtable_3_10_12.size() != 0;
+ const bool have_31013 = this->subtable_3_10_13.size() != 0;
const uint16_t num_subtables = static_cast<uint16_t>(have_034) +
static_cast<uint16_t>(have_0514) +
static_cast<uint16_t>(have_100) +
@@ -860,7 +857,7 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
// Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
// (e.g., old fonts for Mac). We don't support them.
if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) {
- return OTS_FAILURE_MSG("no supported subtables were found");
+ return Error("no supported subtables were found");
}
if (!out->WriteU16(0) ||
@@ -875,8 +872,8 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
const off_t offset_034 = out->Tell();
if (have_034) {
- if (!out->Write(font->cmap->subtable_0_3_4_data,
- font->cmap->subtable_0_3_4_length)) {
+ if (!out->Write(this->subtable_0_3_4_data,
+ this->subtable_0_3_4_length)) {
return OTS_FAILURE();
}
}
@@ -884,10 +881,10 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
const off_t offset_0514 = out->Tell();
if (have_0514) {
const std::vector<ots::OpenTypeCMAPSubtableVSRecord> &records
- = font->cmap->subtable_0_5_14;
+ = this->subtable_0_5_14;
const unsigned num_records = records.size();
if (!out->WriteU16(14) ||
- !out->WriteU32(font->cmap->subtable_0_5_14_length) ||
+ !out->WriteU32(this->subtable_0_5_14_length) ||
!out->WriteU32(num_records)) {
return OTS_FAILURE();
}
@@ -939,23 +936,23 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
!out->WriteU16(0)) { // language
return OTS_FAILURE();
}
- if (!out->Write(&(font->cmap->subtable_1_0_0[0]), kFormat0ArraySize)) {
+ if (!out->Write(&(this->subtable_1_0_0[0]), kFormat0ArraySize)) {
return OTS_FAILURE();
}
}
const off_t offset_304 = out->Tell();
if (have_304) {
- if (!out->Write(font->cmap->subtable_3_0_4_data,
- font->cmap->subtable_3_0_4_length)) {
+ if (!out->Write(this->subtable_3_0_4_data,
+ this->subtable_3_0_4_length)) {
return OTS_FAILURE();
}
}
const off_t offset_314 = out->Tell();
if (have_314) {
- if (!out->Write(font->cmap->subtable_3_1_4_data,
- font->cmap->subtable_3_1_4_length)) {
+ if (!out->Write(this->subtable_3_1_4_data,
+ this->subtable_3_1_4_length)) {
return OTS_FAILURE();
}
}
@@ -963,7 +960,7 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
const off_t offset_31012 = out->Tell();
if (have_31012) {
std::vector<OpenTypeCMAPSubtableRange> &groups
- = font->cmap->subtable_3_10_12;
+ = this->subtable_3_10_12;
const unsigned num_groups = groups.size();
if (!out->WriteU16(12) ||
!out->WriteU16(0) ||
@@ -985,7 +982,7 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
const off_t offset_31013 = out->Tell();
if (have_31013) {
std::vector<OpenTypeCMAPSubtableRange> &groups
- = font->cmap->subtable_3_10_13;
+ = this->subtable_3_10_13;
const unsigned num_groups = groups.size();
if (!out->WriteU16(13) ||
!out->WriteU16(0) ||
@@ -1074,15 +1071,4 @@ bool ots_cmap_serialise(OTSStream *out, Font *font) {
return true;
}
-void ots_cmap_reuse(Font *font, Font *other) {
- font->cmap = other->cmap;
- font->cmap_reused = true;
-}
-
-void ots_cmap_free(Font *font) {
- delete font->cmap;
-}
-
} // namespace ots
-
-#undef TABLE_NAME