Coverage Report

Created: 2026-06-14 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ots/src/maxp.cc
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 "maxp.h"
6
7
// maxp - Maximum Profile
8
// http://www.microsoft.com/typography/otspec/maxp.htm
9
10
namespace ots {
11
12
77.2k
bool OpenTypeMAXP::Parse(const uint8_t *data, size_t length) {
13
77.2k
  Buffer table(data, length);
14
15
77.2k
  uint32_t version = 0;
16
77.2k
  if (!table.ReadU32(&version)) {
17
43
    return Error("Failed to read table version");
18
43
  }
19
20
77.2k
  if (version >> 16 > 1) {
21
116
    return Error("Unsupported table version 0x%x", version);
22
116
  }
23
24
77.0k
  if (!table.ReadU16(&this->num_glyphs)) {
25
39
    return Error("Failed to read numGlyphs");
26
39
  }
27
28
77.0k
  if (!this->num_glyphs) {
29
35
    return Error("numGlyphs is 0");
30
35
  }
31
32
77.0k
  this->version_1 = false;
33
34
  // Per https://learn.microsoft.com/en-gb/typography/opentype/spec/maxp,
35
  // the only two 'maxp' version numbers are 0.5 (for CFF/CFF2) and 1.0
36
  // (for TrueType).
37
  // If it's version 0.5, there is nothing more to read.
38
77.0k
  if (version == 0x00005000) {
39
2.41k
    return true;
40
2.41k
  }
41
42
74.6k
  if (version != 0x00010000) {
43
67.3k
    Warning("Unexpected version 0x%08x; attempting to read as version 1.0",
44
67.3k
            version);
45
67.3k
  }
46
47
  // Otherwise, try to read the version 1.0 fields:
48
74.6k
  if (!table.ReadU16(&this->max_points) ||
49
74.1k
      !table.ReadU16(&this->max_contours) ||
50
73.6k
      !table.ReadU16(&this->max_c_points) ||
51
73.5k
      !table.ReadU16(&this->max_c_contours) ||
52
69.3k
      !table.ReadU16(&this->max_zones) ||
53
66.9k
      !table.ReadU16(&this->max_t_points) ||
54
66.4k
      !table.ReadU16(&this->max_storage) ||
55
66.2k
      !table.ReadU16(&this->max_fdefs) ||
56
65.8k
      !table.ReadU16(&this->max_idefs) ||
57
65.5k
      !table.ReadU16(&this->max_stack) ||
58
65.1k
      !table.ReadU16(&this->max_size_glyf_instructions) ||
59
64.7k
      !table.ReadU16(&this->max_c_components) ||
60
64.5k
      !table.ReadU16(&this->max_c_depth)) {
61
11.8k
    Warning("Failed to read version 1.0 fields, downgrading to version 0.5");
62
11.8k
    return true;
63
11.8k
  }
64
65
62.7k
  this->version_1 = true;
66
67
62.7k
  if (this->max_zones < 1) {
68
    // workaround for ipa*.ttf Japanese fonts.
69
30.3k
    Warning("Bad maxZones: %u", this->max_zones);
70
30.3k
    this->max_zones = 1;
71
32.3k
  } else if (this->max_zones > 2) {
72
    // workaround for Ecolier-*.ttf fonts and bad fonts in some PDFs
73
18.3k
    Warning("Bad maxZones: %u", this->max_zones);
74
18.3k
    this->max_zones = 2;
75
18.3k
  }
76
77
62.7k
  return true;
78
74.6k
}
79
80
35.4k
bool OpenTypeMAXP::Serialize(OTSStream *out) {
81
35.4k
  if (!out->WriteU32(this->version_1 ? 0x00010000 : 0x00005000) ||
82
35.4k
      !out->WriteU16(this->num_glyphs)) {
83
0
    return Error("Failed to write version or numGlyphs");
84
0
  }
85
86
35.4k
  if (!this->version_1) return true;
87
88
35.3k
  if (!out->WriteU16(this->max_points) ||
89
35.3k
      !out->WriteU16(this->max_contours) ||
90
35.3k
      !out->WriteU16(this->max_c_points) ||
91
35.3k
      !out->WriteU16(this->max_c_contours)) {
92
0
    return Error("Failed to write maxp");
93
0
  }
94
95
35.3k
  if (!out->WriteU16(this->max_zones) ||
96
35.3k
      !out->WriteU16(this->max_t_points) ||
97
35.3k
      !out->WriteU16(this->max_storage) ||
98
35.3k
      !out->WriteU16(this->max_fdefs) ||
99
35.3k
      !out->WriteU16(this->max_idefs) ||
100
35.3k
      !out->WriteU16(this->max_stack) ||
101
35.3k
      !out->WriteU16(this->max_size_glyf_instructions)) {
102
0
    return Error("Failed to write more maxp");
103
0
  }
104
105
35.3k
  if (!out->WriteU16(this->max_c_components) ||
106
35.3k
      !out->WriteU16(this->max_c_depth)) {
107
0
    return Error("Failed to write yet more maxp");
108
0
  }
109
110
35.3k
  return true;
111
35.3k
}
112
113
}  // namespace ots