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 |