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 | 1.99k | if (this->version >> 16 != 1) { |
23 | 690 | return DropGraphite("Unsupported table version: %u", this->version >> 16); |
24 | 690 | } |
25 | 1.30k | if (!table.ReadU16(&this->flags) || this->flags > 0b11) { |
26 | 58 | return DropGraphite("Failed to read valid flags"); |
27 | 58 | } |
28 | 1.24k | if (!table.ReadU16(&this->numAttribs)) { |
29 | 20 | return DropGraphite("Failed to read numAttribs"); |
30 | 20 | } |
31 | | |
32 | 1.22k | 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.20k | size_t locations_len = (table.remaining() - |
37 | 1.20k | (this->flags & ATTRIB_IDS ? this->numAttribs * sizeof(uint16_t) : 0)) / |
38 | 1.20k | (this->flags & LONG_FORMAT ? sizeof(uint32_t) : sizeof(uint16_t)); |
39 | | //this->locations.resize(locations_len); |
40 | 1.20k | if (this->flags & LONG_FORMAT) { |
41 | 814 | unsigned long last_location = 0; |
42 | 93.6k | for (size_t i = 0; i < locations_len; ++i) { |
43 | 92.9k | this->locations.emplace_back(); |
44 | 92.9k | uint32_t& location = this->locations[i]; |
45 | 92.9k | if (!table.ReadU32(&location) || location < last_location) { |
46 | 61 | return DropGraphite("Failed to read valid locations[%lu]", i); |
47 | 61 | } |
48 | 92.8k | last_location = location; |
49 | 92.8k | } |
50 | 814 | } else { // short (16-bit) offsets |
51 | 391 | unsigned last_location = 0; |
52 | 43.9k | for (size_t i = 0; i < locations_len; ++i) { |
53 | 43.8k | uint16_t location; |
54 | 43.8k | if (!table.ReadU16(&location) || location < last_location) { |
55 | 220 | return DropGraphite("Failed to read valid locations[%lu]", i); |
56 | 220 | } |
57 | 43.5k | last_location = location; |
58 | 43.5k | this->locations.push_back(static_cast<uint32_t>(location)); |
59 | 43.5k | } |
60 | 391 | } |
61 | 924 | if (this->locations.empty()) { |
62 | 28 | return DropGraphite("No locations"); |
63 | 28 | } |
64 | | |
65 | 896 | 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 | 877 | if (table.remaining()) { |
77 | 407 | return Warning("%zu bytes unparsed", table.remaining()); |
78 | 407 | } |
79 | 470 | return true; |
80 | 877 | } |
81 | | |
82 | 141 | bool OpenTypeGLOC::Serialize(OTSStream* out) { |
83 | 141 | if (!out->WriteU32(this->version) || |
84 | 141 | !out->WriteU16(this->flags) || |
85 | 141 | !out->WriteU16(this->numAttribs) || |
86 | 141 | (this->flags & LONG_FORMAT ? !SerializeParts(this->locations, out) : |
87 | 141 | ![&] { |
88 | 11.8k | for (uint32_t location : this->locations) { |
89 | 11.8k | if (!out->WriteU16(static_cast<uint16_t>(location))) { |
90 | 0 | return false; |
91 | 0 | } |
92 | 11.8k | } |
93 | 57 | return true; |
94 | 57 | }()) || |
95 | 141 | (this->flags & ATTRIB_IDS && !SerializeParts(this->attribIds, out))) { |
96 | 0 | return Error("Failed to write table"); |
97 | 0 | } |
98 | 141 | return true; |
99 | 141 | } |
100 | | |
101 | 516 | const std::vector<uint32_t>& OpenTypeGLOC::GetLocations() { |
102 | 516 | return this->locations; |
103 | 516 | } |
104 | | |
105 | | } // namespace ots |