Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/ots/src/avar.cc
Line
Count
Source (jump to first uncovered line)
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.
4
5
#include "avar.h"
6
7
#include "fvar.h"
8
9
namespace ots {
10
11
// -----------------------------------------------------------------------------
12
// OpenTypeAVAR
13
// -----------------------------------------------------------------------------
14
15
0
bool OpenTypeAVAR::Parse(const uint8_t* data, size_t length) {
16
0
  Buffer table(data, length);
17
0
  if (!table.ReadU16(&this->majorVersion) ||
18
0
      !table.ReadU16(&this->minorVersion) ||
19
0
      !table.ReadU16(&this->reserved) ||
20
0
      !table.ReadU16(&this->axisCount)) {
21
0
    return Drop("Failed to read table header");
22
0
  }
23
0
  if (this->majorVersion != 1) {
24
0
    return Drop("Unknown table version");
25
0
  }
26
0
  if (this->minorVersion > 0) {
27
0
    // we only know how to serialize version 1.0
28
0
    Warning("Downgrading minor version to 0");
29
0
    this->minorVersion = 0;
30
0
  }
31
0
  if (this->reserved != 0) {
32
0
    Warning("Expected reserved=0");
33
0
    this->reserved = 0;
34
0
  }
35
0
36
0
  OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(
37
0
      GetFont()->GetTypedTable(OTS_TAG_FVAR));
38
0
  if (!fvar) {
39
0
    return DropVariations("Required fvar table is missing");
40
0
  }
41
0
  if (axisCount != fvar->AxisCount()) {
42
0
    return Drop("Axis count mismatch");
43
0
  }
44
0
45
0
  for (size_t i = 0; i < this->axisCount; i++) {
46
0
    this->axisSegmentMaps.emplace_back();
47
0
    uint16_t positionMapCount;
48
0
    if (!table.ReadU16(&positionMapCount)) {
49
0
      return Drop("Failed to read position map count");
50
0
    }
51
0
    int foundRequiredMappings = 0;
52
0
    for (size_t j = 0; j < positionMapCount; j++) {
53
0
      AxisValueMap map;
54
0
      if (!table.ReadS16(&map.fromCoordinate) ||
55
0
          !table.ReadS16(&map.toCoordinate)) {
56
0
        return Drop("Failed to read axis value map");
57
0
      }
58
0
      if (map.fromCoordinate < -0x4000 ||
59
0
          map.fromCoordinate > 0x4000 ||
60
0
          map.toCoordinate < -0x4000 ||
61
0
          map.toCoordinate > 0x4000) {
62
0
        return Drop("Axis value map coordinate out of range");
63
0
      }
64
0
      if (j > 0) {
65
0
        if (map.fromCoordinate <= this->axisSegmentMaps[i].back().fromCoordinate ||
66
0
            map.toCoordinate < this->axisSegmentMaps[i].back().toCoordinate) {
67
0
          return Drop("Axis value map out of order");
68
0
        }
69
0
      }
70
0
      if ((map.fromCoordinate == -0x4000 && map.toCoordinate == -0x4000) ||
71
0
          (map.fromCoordinate == 0 && map.toCoordinate == 0) ||
72
0
          (map.fromCoordinate == 0x4000 && map.toCoordinate == 0x4000)) {
73
0
        ++foundRequiredMappings;
74
0
      }
75
0
      this->axisSegmentMaps[i].push_back(map);
76
0
    }
77
0
    if (positionMapCount > 0 && foundRequiredMappings != 3) {
78
0
      return Drop("A required mapping (for -1, 0 or 1) is missing");
79
0
    }
80
0
  }
81
0
82
0
  return true;
83
0
}
84
85
0
bool OpenTypeAVAR::Serialize(OTSStream* out) {
86
0
  if (!out->WriteU16(this->majorVersion) ||
87
0
      !out->WriteU16(this->minorVersion) ||
88
0
      !out->WriteU16(this->reserved) ||
89
0
      !out->WriteU16(this->axisCount)) {
90
0
    return Error("Failed to write table");
91
0
  }
92
0
93
0
  for (size_t i = 0; i < this->axisCount; i++) {
94
0
    const auto& axisValueMap = this->axisSegmentMaps[i];
95
0
    if (!out->WriteU16(axisValueMap.size())) {
96
0
      return Error("Failed to write table");
97
0
    }
98
0
    for (size_t j = 0; j < axisValueMap.size(); j++) {
99
0
      if (!out->WriteS16(axisValueMap[j].fromCoordinate) ||
100
0
          !out->WriteS16(axisValueMap[j].toCoordinate)) {
101
0
        return Error("Failed to write table");
102
0
      }
103
0
    }
104
0
  }
105
0
106
0
  return true;
107
0
}
108
109
}  // namespace ots