Bug 1601406 [wpt PR 20618] - Advertise DocumentPolicy & Network Err when receive...
[gecko.git] / gfx / ots / src / fvar.cc
blob6f9b4d6ebff5077f338e414cfdf45b1a1f2451a5
1 // Copyright (c) 2018 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.
5 #include "fvar.h"
7 namespace ots {
9 // -----------------------------------------------------------------------------
10 // OpenTypeFVAR
11 // -----------------------------------------------------------------------------
13 bool OpenTypeFVAR::Parse(const uint8_t* data, size_t length) {
14 Buffer table(data, length);
15 if (!table.ReadU16(&this->majorVersion) ||
16 !table.ReadU16(&this->minorVersion) ||
17 !table.ReadU16(&this->axesArrayOffset) ||
18 !table.ReadU16(&this->reserved) ||
19 !table.ReadU16(&this->axisCount) ||
20 !table.ReadU16(&this->axisSize) ||
21 !table.ReadU16(&this->instanceCount) ||
22 !table.ReadU16(&this->instanceSize)) {
23 return DropVariations("Failed to read table header");
25 if (this->majorVersion != 1) {
26 return DropVariations("Unknown table version");
28 if (this->minorVersion > 0) {
29 Warning("Downgrading minor version to 0");
30 this->minorVersion = 0;
32 if (this->axesArrayOffset > length || this->axesArrayOffset < table.offset()) {
33 return DropVariations("Bad axesArrayOffset");
35 if (this->reserved != 2) {
36 Warning("Expected reserved=2");
37 this->reserved = 2;
39 if (this->axisCount == 0) {
40 return DropVariations("No variation axes");
42 if (this->axisSize != 20) {
43 return DropVariations("Invalid axisSize");
45 // instanceCount is not validated
46 if (this->instanceSize == this->axisCount * sizeof(Fixed) + 6) {
47 this->instancesHavePostScriptNameID = true;
48 } else if (this->instanceSize == this->axisCount * sizeof(Fixed) + 4) {
49 this->instancesHavePostScriptNameID = false;
50 } else {
51 return DropVariations("Invalid instanceSize");
54 // When we serialize, the axes array will go here, even if it was
55 // originally at a different offset. So we update the axesArrayOffset
56 // field for the header.
57 uint32_t origAxesArrayOffset = this->axesArrayOffset;
58 this->axesArrayOffset = table.offset();
60 table.set_offset(origAxesArrayOffset);
61 for (unsigned i = 0; i < this->axisCount; i++) {
62 this->axes.emplace_back();
63 auto& axis = this->axes[i];
64 if (!table.ReadU32(&axis.axisTag) ||
65 !table.ReadS32(&axis.minValue) ||
66 !table.ReadS32(&axis.defaultValue) ||
67 !table.ReadS32(&axis.maxValue) ||
68 !table.ReadU16(&axis.flags) ||
69 !table.ReadU16(&axis.axisNameID)) {
70 return DropVariations("Failed to read axis record");
72 if (!CheckTag(axis.axisTag)) {
73 return DropVariations("Bad axis tag");
75 if (!(axis.minValue <= axis.defaultValue && axis.defaultValue <= axis.maxValue)) {
76 return DropVariations("Bad axis value range");
78 if ((axis.flags & 0xFFFEu) != 0) {
79 Warning("Discarding unknown axis flags");
80 axis.flags &= ~0xFFFEu;
82 if (axis.axisNameID <= 255 || axis.axisNameID >= 32768) {
83 Warning("Axis nameID out of range");
84 // We don't check that the name actually exists -- assume the client can handle
85 // a missing name when it tries to read the table.
89 for (unsigned i = 0; i < this->instanceCount; i++) {
90 this->instances.emplace_back();
91 auto& inst = this->instances[i];
92 if (!table.ReadU16(&inst.subfamilyNameID) ||
93 !table.ReadU16(&inst.flags)) {
94 return DropVariations("Failed to read instance record");
96 inst.coordinates.reserve(this->axisCount);
97 for (unsigned j = 0; j < this->axisCount; j++) {
98 inst.coordinates.emplace_back();
99 auto& coord = inst.coordinates[j];
100 if (!table.ReadS32(&coord)) {
101 return DropVariations("Failed to read instance coordinates");
104 if (this->instancesHavePostScriptNameID) {
105 if (!table.ReadU16(&inst.postScriptNameID)) {
106 return DropVariations("Failed to read instance psname ID");
111 if (table.remaining()) {
112 return Warning("%zu bytes unparsed", table.remaining());
115 return true;
118 bool OpenTypeFVAR::Serialize(OTSStream* out) {
119 if (!out->WriteU16(this->majorVersion) ||
120 !out->WriteU16(this->minorVersion) ||
121 !out->WriteU16(this->axesArrayOffset) ||
122 !out->WriteU16(this->reserved) ||
123 !out->WriteU16(this->axisCount) ||
124 !out->WriteU16(this->axisSize) ||
125 !out->WriteU16(this->instanceCount) ||
126 !out->WriteU16(this->instanceSize)) {
127 return Error("Failed to write table");
130 for (unsigned i = 0; i < this->axisCount; i++) {
131 const auto& axis = this->axes[i];
132 if (!out->WriteU32(axis.axisTag) ||
133 !out->WriteS32(axis.minValue) ||
134 !out->WriteS32(axis.defaultValue) ||
135 !out->WriteS32(axis.maxValue) ||
136 !out->WriteU16(axis.flags) ||
137 !out->WriteU16(axis.axisNameID)) {
138 return Error("Failed to write table");
142 for (unsigned i = 0; i < this->instanceCount; i++) {
143 const auto& inst = this->instances[i];
144 if (!out->WriteU16(inst.subfamilyNameID) ||
145 !out->WriteU16(inst.flags)) {
146 return Error("Failed to write table");
148 for (unsigned j = 0; j < this->axisCount; j++) {
149 const auto& coord = inst.coordinates[j];
150 if (!out->WriteS32(coord)) {
151 return Error("Failed to write table");
154 if (this->instancesHavePostScriptNameID) {
155 if (!out->WriteU16(inst.postScriptNameID)) {
156 return Error("Failed to write table");
161 return true;
164 } // namespace ots