Line | Count | Source |
1 | | // Copyright (c) 2009-2017 The OTS Authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #include "gloc.h" |
6 | | |
7 | | #include "name.h" |
8 | | |
9 | | namespace ots { |
10 | | |
11 | 2.01k | bool OpenTypeGLOC::Parse(const uint8_t* data, size_t length) { |
12 | 2.01k | Buffer table(data, length); |
13 | 2.01k | OpenTypeNAME* name = static_cast<OpenTypeNAME*>( |
14 | 2.01k | GetFont()->GetTypedTable(OTS_TAG_NAME)); |
15 | 2.01k | if (!name) { |
16 | 0 | return DropGraphite("Required name table is missing"); |
17 | 0 | } |
18 | | |
19 | 2.01k | if (!table.ReadU32(&this->version)) { |
20 | 16 | return DropGraphite("Failed to read version"); |
21 | 16 | } |
22 | 2.00k | if (this->version >> 16 != 1) { |
23 | 690 | return DropGraphite("Unsupported table version: %u", this->version >> 16); |
24 | 690 | } |
25 | 1.31k | if (!table.ReadU16(&this->flags) || this->flags > 0b11) { |
26 | 58 | return DropGraphite("Failed to read valid flags"); |
27 | 58 | } |
28 | 1.25k | if (!table.ReadU16(&this->numAttribs)) { |
29 | 20 | return DropGraphite("Failed to read numAttribs"); |
30 | 20 | } |
31 | | |
32 | 1.23k | if (this->flags & ATTRIB_IDS && this->numAttribs * sizeof(uint16_t) > |
33 | 70 | table.remaining()) { |
34 | 22 | return DropGraphite("Failed to calculate length of locations"); |
35 | 22 | } |
36 | 1.21k | size_t locations_len = (table.remaining() - |
37 | 1.21k | (this->flags & ATTRIB_IDS ? this->numAttribs * sizeof(uint16_t) : 0)) / |
38 | 1.21k | (this->flags & LONG_FORMAT ? sizeof(uint32_t) : sizeof(uint16_t)); |
39 | | //this->locations.resize(locations_len); |
40 | 1.21k | if (this->flags & LONG_FORMAT) { |
41 | 819 | unsigned long last_location = 0; |
42 | 95.2k | for (size_t i = 0; i < locations_len; ++i) { |
43 | 94.5k | this->locations.emplace_back(); |
44 | 94.5k | uint32_t& location = this->locations[i]; |
45 | 94.5k | if (!table.ReadU32(&location) || location < last_location) { |
46 | 61 | return DropGraphite("Failed to read valid locations[%lu]", i); |
47 | 61 | } |
48 | 94.4k | last_location = location; |
49 | 94.4k | } |
50 | 819 | } else { // short (16-bit) offsets |
51 | 392 | unsigned last_location = 0; |
52 | 45.3k | for (size_t i = 0; i < locations_len; ++i) { |
53 | 45.1k | uint16_t location; |
54 | 45.1k | if (!table.ReadU16(&location) || location < last_location) { |
55 | 220 | return DropGraphite("Failed to read valid locations[%lu]", i); |
56 | 220 | } |
57 | 44.9k | last_location = location; |
58 | 44.9k | this->locations.push_back(static_cast<uint32_t>(location)); |
59 | 44.9k | } |
60 | 392 | } |
61 | 930 | if (this->locations.empty()) { |
62 | 28 | return DropGraphite("No locations"); |
63 | 28 | } |
64 | | |
65 | 902 | if (this->flags & ATTRIB_IDS) { // attribIds array present |
66 | | //this->attribIds.resize(numAttribs); |
67 | 97 | for (unsigned i = 0; i < this->numAttribs; ++i) { |
68 | 79 | this->attribIds.emplace_back(); |
69 | 79 | if (!table.ReadU16(&this->attribIds[i]) || |
70 | 79 | !name->IsValidNameId(this->attribIds[i])) { |
71 | 19 | return DropGraphite("Failed to read valid attribIds[%u]", i); |
72 | 19 | } |
73 | 79 | } |
74 | 37 | } |
75 | | |
76 | 883 | if (table.remaining()) { |
77 | 404 | return Warning("%zu bytes unparsed", table.remaining()); |
78 | 404 | } |
79 | 479 | return true; |
80 | 883 | } |
81 | | |
82 | 140 | bool OpenTypeGLOC::Serialize(OTSStream* out) { |
83 | 140 | if (!out->WriteU32(this->version) || |
84 | 140 | !out->WriteU16(this->flags) || |
85 | 140 | !out->WriteU16(this->numAttribs) || |
86 | 140 | (this->flags & LONG_FORMAT ? !SerializeParts(this->locations, out) : |
87 | 140 | ![&] { |
88 | 11.6k | for (uint32_t location : this->locations) { |
89 | 11.6k | if (!out->WriteU16(static_cast<uint16_t>(location))) { |
90 | 0 | return false; |
91 | 0 | } |
92 | 11.6k | } |
93 | 56 | return true; |
94 | 56 | }()) || |
95 | 140 | (this->flags & ATTRIB_IDS && !SerializeParts(this->attribIds, out))) { |
96 | 0 | return Error("Failed to write table"); |
97 | 0 | } |
98 | 140 | return true; |
99 | 140 | } |
100 | | |
101 | 518 | const std::vector<uint32_t>& OpenTypeGLOC::GetLocations() { |
102 | 518 | return this->locations; |
103 | 518 | } |
104 | | |
105 | | } // namespace ots |