Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: src/metrics.cc

Issue 658573004: Updating to new OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/external/ots@master
Patch Set: Adding Colored Emoji changes from external/git repo Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« .gitmodules ('K') | « src/metrics.h ('k') | src/name.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "metrics.h" 5 #include "metrics.h"
6 6
7 #include "head.h" 7 #include "head.h"
8 #include "maxp.h" 8 #include "maxp.h"
9 9
10 // OpenType horizontal and vertical common header format 10 // OpenType horizontal and vertical common header format
11 // http://www.microsoft.com/opentype/otspec/hhea.htm 11 // http://www.microsoft.com/typography/otspec/hhea.htm
12 // http://www.microsoft.com/opentype/otspec/vhea.htm 12 // http://www.microsoft.com/typography/otspec/vhea.htm
13
14 #define TABLE_NAME "metrics" // XXX: use individual table names
13 15
14 namespace ots { 16 namespace ots {
15 17
16 bool ParseMetricsHeader(OpenTypeFile *file, Buffer *table, 18 bool ParseMetricsHeader(OpenTypeFile *file, Buffer *table,
17 OpenTypeMetricsHeader *header) { 19 OpenTypeMetricsHeader *header) {
18 if (!table->ReadS16(&header->ascent) || 20 if (!table->ReadS16(&header->ascent) ||
19 !table->ReadS16(&header->descent) || 21 !table->ReadS16(&header->descent) ||
20 !table->ReadS16(&header->linegap) || 22 !table->ReadS16(&header->linegap) ||
21 !table->ReadU16(&header->adv_width_max) || 23 !table->ReadU16(&header->adv_width_max) ||
22 !table->ReadS16(&header->min_sb1) || 24 !table->ReadS16(&header->min_sb1) ||
23 !table->ReadS16(&header->min_sb2) || 25 !table->ReadS16(&header->min_sb2) ||
24 !table->ReadS16(&header->max_extent) || 26 !table->ReadS16(&header->max_extent) ||
25 !table->ReadS16(&header->caret_slope_rise) || 27 !table->ReadS16(&header->caret_slope_rise) ||
26 !table->ReadS16(&header->caret_slope_run) || 28 !table->ReadS16(&header->caret_slope_run) ||
27 !table->ReadS16(&header->caret_offset)) { 29 !table->ReadS16(&header->caret_offset)) {
28 return OTS_FAILURE(); 30 return OTS_FAILURE_MSG("Failed to read metrics header");
29 } 31 }
30 32
31 if (header->ascent < 0) { 33 if (header->ascent < 0) {
32 OTS_WARNING("bad ascent: %d", header->ascent); 34 OTS_WARNING("bad ascent: %d", header->ascent);
33 header->ascent = 0; 35 header->ascent = 0;
34 } 36 }
35 if (header->linegap < 0) { 37 if (header->linegap < 0) {
36 OTS_WARNING("bad linegap: %d", header->linegap); 38 OTS_WARNING("bad linegap: %d", header->linegap);
37 header->linegap = 0; 39 header->linegap = 0;
38 } 40 }
39 41
40 if (!file->head) { 42 if (!file->head) {
41 return OTS_FAILURE(); 43 return OTS_FAILURE_MSG("Missing head font table");
42 } 44 }
43 45
44 // if the font is non-slanted, caret_offset should be zero. 46 // if the font is non-slanted, caret_offset should be zero.
45 if (!(file->head->mac_style & 2) && 47 if (!(file->head->mac_style & 2) &&
46 (header->caret_offset != 0)) { 48 (header->caret_offset != 0)) {
47 OTS_WARNING("bad caret offset: %d", header->caret_offset); 49 OTS_WARNING("bad caret offset: %d", header->caret_offset);
48 header->caret_offset = 0; 50 header->caret_offset = 0;
49 } 51 }
50 52
51 // skip the reserved bytes 53 // skip the reserved bytes
52 if (!table->Skip(8)) { 54 if (!table->Skip(8)) {
53 return OTS_FAILURE(); 55 return OTS_FAILURE_MSG("Failed to skip reserverd bytes");
54 } 56 }
55 57
56 int16_t data_format; 58 int16_t data_format;
57 if (!table->ReadS16(&data_format)) { 59 if (!table->ReadS16(&data_format)) {
58 return OTS_FAILURE(); 60 return OTS_FAILURE_MSG("Failed to read data format");
59 } 61 }
60 if (data_format) { 62 if (data_format) {
61 return OTS_FAILURE(); 63 return OTS_FAILURE_MSG("Bad data format %d", data_format);
62 } 64 }
63 65
64 if (!table->ReadU16(&header->num_metrics)) { 66 if (!table->ReadU16(&header->num_metrics)) {
65 return OTS_FAILURE(); 67 return OTS_FAILURE_MSG("Failed to read number of metrics");
66 } 68 }
67 69
68 if (!file->maxp) { 70 if (!file->maxp) {
69 return OTS_FAILURE(); 71 return OTS_FAILURE_MSG("Missing maxp font table");
70 } 72 }
71 73
72 if (header->num_metrics > file->maxp->num_glyphs) { 74 if (header->num_metrics > file->maxp->num_glyphs) {
73 return OTS_FAILURE(); 75 return OTS_FAILURE_MSG("Bad number of metrics %d", header->num_metrics);
74 } 76 }
75 77
76 return true; 78 return true;
77 } 79 }
78 80
79 bool SerialiseMetricsHeader(OTSStream *out, 81 bool SerialiseMetricsHeader(const ots::OpenTypeFile *file,
82 OTSStream *out,
80 const OpenTypeMetricsHeader *header) { 83 const OpenTypeMetricsHeader *header) {
81 if (!out->WriteU32(header->version) || 84 if (!out->WriteU32(header->version) ||
82 !out->WriteS16(header->ascent) || 85 !out->WriteS16(header->ascent) ||
83 !out->WriteS16(header->descent) || 86 !out->WriteS16(header->descent) ||
84 !out->WriteS16(header->linegap) || 87 !out->WriteS16(header->linegap) ||
85 !out->WriteU16(header->adv_width_max) || 88 !out->WriteU16(header->adv_width_max) ||
86 !out->WriteS16(header->min_sb1) || 89 !out->WriteS16(header->min_sb1) ||
87 !out->WriteS16(header->min_sb2) || 90 !out->WriteS16(header->min_sb2) ||
88 !out->WriteS16(header->max_extent) || 91 !out->WriteS16(header->max_extent) ||
89 !out->WriteS16(header->caret_slope_rise) || 92 !out->WriteS16(header->caret_slope_rise) ||
90 !out->WriteS16(header->caret_slope_run) || 93 !out->WriteS16(header->caret_slope_run) ||
91 !out->WriteS16(header->caret_offset) || 94 !out->WriteS16(header->caret_offset) ||
92 !out->WriteR64(0) || // reserved 95 !out->WriteR64(0) || // reserved
93 !out->WriteS16(0) || // metric data format 96 !out->WriteS16(0) || // metric data format
94 !out->WriteU16(header->num_metrics)) { 97 !out->WriteU16(header->num_metrics)) {
95 return OTS_FAILURE(); 98 return OTS_FAILURE_MSG("Failed to write metrics");
96 } 99 }
97 100
98 return true; 101 return true;
99 } 102 }
100 103
101 bool ParseMetricsTable(Buffer *table, 104 bool ParseMetricsTable(const ots::OpenTypeFile *file,
105 Buffer *table,
102 const uint16_t num_glyphs, 106 const uint16_t num_glyphs,
103 const OpenTypeMetricsHeader *header, 107 const OpenTypeMetricsHeader *header,
104 OpenTypeMetricsTable *metrics) { 108 OpenTypeMetricsTable *metrics) {
105 // |num_metrics| is a uint16_t, so it's bounded < 65536. This limits that 109 // |num_metrics| is a uint16_t, so it's bounded < 65536. This limits that
106 // amount of memory that we'll allocate for this to a sane amount. 110 // amount of memory that we'll allocate for this to a sane amount.
107 const unsigned num_metrics = header->num_metrics; 111 const unsigned num_metrics = header->num_metrics;
108 112
109 if (num_metrics > num_glyphs) { 113 if (num_metrics > num_glyphs) {
110 return OTS_FAILURE(); 114 return OTS_FAILURE_MSG("Bad number of metrics %d", num_metrics);
111 } 115 }
112 if (!num_metrics) { 116 if (!num_metrics) {
113 return OTS_FAILURE(); 117 return OTS_FAILURE_MSG("No metrics!");
114 } 118 }
115 const unsigned num_sbs = num_glyphs - num_metrics; 119 const unsigned num_sbs = num_glyphs - num_metrics;
116 120
117 metrics->entries.reserve(num_metrics); 121 metrics->entries.reserve(num_metrics);
118 for (unsigned i = 0; i < num_metrics; ++i) { 122 for (unsigned i = 0; i < num_metrics; ++i) {
119 uint16_t adv = 0; 123 uint16_t adv = 0;
120 int16_t sb = 0; 124 int16_t sb = 0;
121 if (!table->ReadU16(&adv) || !table->ReadS16(&sb)) { 125 if (!table->ReadU16(&adv) || !table->ReadS16(&sb)) {
122 return OTS_FAILURE(); 126 return OTS_FAILURE_MSG("Failed to read metric %d", i);
123 } 127 }
124 128
129 // This check is bogus, see https://github.com/khaledhosny/ots/issues/36
130 #if 0
125 // Since so many fonts don't have proper value on |adv| and |sb|, 131 // Since so many fonts don't have proper value on |adv| and |sb|,
126 // we should not call ots_failure() here. For example, about 20% of fonts 132 // we should not call ots_failure() here. For example, about 20% of fonts
127 // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests. 133 // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
128 if (adv > header->adv_width_max) { 134 if (adv > header->adv_width_max) {
129 OTS_WARNING("bad adv: %u > %u", adv, header->adv_width_max); 135 OTS_WARNING("bad adv: %u > %u", adv, header->adv_width_max);
130 adv = header->adv_width_max; 136 adv = header->adv_width_max;
131 } 137 }
132 138
133 if (sb < header->min_sb1) { 139 if (sb < header->min_sb1) {
134 OTS_WARNING("bad sb: %d < %d", sb, header->min_sb1); 140 OTS_WARNING("bad sb: %d < %d", sb, header->min_sb1);
135 sb = header->min_sb1; 141 sb = header->min_sb1;
136 } 142 }
143 #endif
137 144
138 metrics->entries.push_back(std::make_pair(adv, sb)); 145 metrics->entries.push_back(std::make_pair(adv, sb));
139 } 146 }
140 147
141 metrics->sbs.reserve(num_sbs); 148 metrics->sbs.reserve(num_sbs);
142 for (unsigned i = 0; i < num_sbs; ++i) { 149 for (unsigned i = 0; i < num_sbs; ++i) {
143 int16_t sb; 150 int16_t sb;
144 if (!table->ReadS16(&sb)) { 151 if (!table->ReadS16(&sb)) {
145 // Some Japanese fonts (e.g., mona.ttf) fail this test. 152 // Some Japanese fonts (e.g., mona.ttf) fail this test.
146 return OTS_FAILURE(); 153 return OTS_FAILURE_MSG("Failed to read side bearing %d", i + num_metrics);
147 } 154 }
148 155
156 // This check is bogus, see https://github.com/khaledhosny/ots/issues/36
157 #if 0
149 if (sb < header->min_sb1) { 158 if (sb < header->min_sb1) {
150 // The same as above. Three fonts in http://www.fontsquirrel.com/fontface 159 // The same as above. Three fonts in http://www.fontsquirrel.com/fontface
151 // (e.g., Notice2Std.otf) have weird lsb values. 160 // (e.g., Notice2Std.otf) have weird lsb values.
152 OTS_WARNING("bad lsb: %d < %d", sb, header->min_sb1); 161 OTS_WARNING("bad lsb: %d < %d", sb, header->min_sb1);
153 sb = header->min_sb1; 162 sb = header->min_sb1;
154 } 163 }
164 #endif
155 165
156 metrics->sbs.push_back(sb); 166 metrics->sbs.push_back(sb);
157 } 167 }
158 168
159 return true; 169 return true;
160 } 170 }
161 171
162 bool SerialiseMetricsTable(OTSStream *out, 172 bool SerialiseMetricsTable(const ots::OpenTypeFile *file,
173 OTSStream *out,
163 const OpenTypeMetricsTable *metrics) { 174 const OpenTypeMetricsTable *metrics) {
164 for (unsigned i = 0; i < metrics->entries.size(); ++i) { 175 for (unsigned i = 0; i < metrics->entries.size(); ++i) {
165 if (!out->WriteU16(metrics->entries[i].first) || 176 if (!out->WriteU16(metrics->entries[i].first) ||
166 !out->WriteS16(metrics->entries[i].second)) { 177 !out->WriteS16(metrics->entries[i].second)) {
167 return OTS_FAILURE(); 178 return OTS_FAILURE_MSG("Failed to write metric %d", i);
168 } 179 }
169 } 180 }
170 181
171 for (unsigned i = 0; i < metrics->sbs.size(); ++i) { 182 for (unsigned i = 0; i < metrics->sbs.size(); ++i) {
172 if (!out->WriteS16(metrics->sbs[i])) { 183 if (!out->WriteS16(metrics->sbs[i])) {
173 return OTS_FAILURE(); 184 return OTS_FAILURE_MSG("Failed to write side bearing %ld", i + metrics->en tries.size());
174 } 185 }
175 } 186 }
176 187
177 return true; 188 return true;
178 } 189 }
179 190
180 } // namespace ots 191 } // namespace ots
181 192
193 #undef TABLE_NAME
OLDNEW
« .gitmodules ('K') | « src/metrics.h ('k') | src/name.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698