OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium 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 "head.h" | |
6 | |
7 #include <cstring> | |
8 | |
9 // head - Font Header | |
10 // http://www.microsoft.com/typography/otspec/head.htm | |
11 | |
12 #define TABLE_NAME "head" | |
13 | |
14 namespace ots { | |
15 | |
16 bool ots_head_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { | |
17 Buffer table(data, length); | |
18 file->head = new OpenTypeHEAD; | |
19 | |
20 uint32_t version = 0; | |
21 if (!table.ReadU32(&version) || | |
22 !table.ReadU32(&file->head->revision)) { | |
23 return OTS_FAILURE_MSG("Failed to read head header"); | |
24 } | |
25 | |
26 if (version >> 16 != 1) { | |
27 return OTS_FAILURE_MSG("Bad head table version of %d", version); | |
28 } | |
29 | |
30 // Skip the checksum adjustment | |
31 if (!table.Skip(4)) { | |
32 return OTS_FAILURE_MSG("Failed to read checksum"); | |
33 } | |
34 | |
35 uint32_t magic; | |
36 if (!table.ReadTag(&magic) || | |
37 std::memcmp(&magic, "\x5F\x0F\x3C\xF5", 4)) { | |
38 return OTS_FAILURE_MSG("Failed to read font magic number"); | |
39 } | |
40 | |
41 if (!table.ReadU16(&file->head->flags)) { | |
42 return OTS_FAILURE_MSG("Failed to read head flags"); | |
43 } | |
44 | |
45 // We allow bits 0..4, 11..13 | |
46 file->head->flags &= 0x381f; | |
47 | |
48 if (!table.ReadU16(&file->head->ppem)) { | |
49 return OTS_FAILURE_MSG("Failed to read pixels per em"); | |
50 } | |
51 | |
52 // ppem must be in range | |
53 if (file->head->ppem < 16 || | |
54 file->head->ppem > 16384) { | |
55 return OTS_FAILURE_MSG("Bad ppm of %d", file->head->ppem); | |
56 } | |
57 | |
58 // ppem must be a power of two | |
59 #if 0 | |
60 // We don't call ots_failure() for now since lots of TrueType fonts are | |
61 // not following this rule. Putting OTS_WARNING here is too noisy. | |
62 if ((file->head->ppem - 1) & file->head->ppem) { | |
63 return OTS_FAILURE_MSG("ppm not a power of two: %d", file->head->ppem); | |
64 } | |
65 #endif | |
66 | |
67 if (!table.ReadR64(&file->head->created) || | |
68 !table.ReadR64(&file->head->modified)) { | |
69 return OTS_FAILURE_MSG("Can't read font dates"); | |
70 } | |
71 | |
72 if (!table.ReadS16(&file->head->xmin) || | |
73 !table.ReadS16(&file->head->ymin) || | |
74 !table.ReadS16(&file->head->xmax) || | |
75 !table.ReadS16(&file->head->ymax)) { | |
76 return OTS_FAILURE_MSG("Failed to read font bounding box"); | |
77 } | |
78 | |
79 if (file->head->xmin > file->head->xmax) { | |
80 return OTS_FAILURE_MSG("Bad x dimension in the font bounding box (%d, %d)",
file->head->xmin, file->head->xmax); | |
81 } | |
82 if (file->head->ymin > file->head->ymax) { | |
83 return OTS_FAILURE_MSG("Bad y dimension in the font bounding box (%d, %d)",
file->head->ymin, file->head->ymax); | |
84 } | |
85 | |
86 if (!table.ReadU16(&file->head->mac_style)) { | |
87 return OTS_FAILURE_MSG("Failed to read font style"); | |
88 } | |
89 | |
90 // We allow bits 0..6 | |
91 file->head->mac_style &= 0x7f; | |
92 | |
93 if (!table.ReadU16(&file->head->min_ppem)) { | |
94 return OTS_FAILURE_MSG("Failed to read font minimum ppm"); | |
95 } | |
96 | |
97 // We don't care about the font direction hint | |
98 if (!table.Skip(2)) { | |
99 return OTS_FAILURE_MSG("Failed to skip font direction hint"); | |
100 } | |
101 | |
102 if (!table.ReadS16(&file->head->index_to_loc_format)) { | |
103 return OTS_FAILURE_MSG("Failed to read index to loc format"); | |
104 } | |
105 if (file->head->index_to_loc_format < 0 || | |
106 file->head->index_to_loc_format > 1) { | |
107 return OTS_FAILURE_MSG("Bad index to loc format %d", file->head->index_to_lo
c_format); | |
108 } | |
109 | |
110 int16_t glyph_data_format; | |
111 if (!table.ReadS16(&glyph_data_format) || | |
112 glyph_data_format) { | |
113 return OTS_FAILURE_MSG("Failed to read glyph data format"); | |
114 } | |
115 | |
116 return true; | |
117 } | |
118 | |
119 bool ots_head_should_serialise(OpenTypeFile *file) { | |
120 return file->head != NULL; | |
121 } | |
122 | |
123 bool ots_head_serialise(OTSStream *out, OpenTypeFile *file) { | |
124 if (!out->WriteU32(0x00010000) || | |
125 !out->WriteU32(file->head->revision) || | |
126 !out->WriteU32(0) || // check sum not filled in yet | |
127 !out->WriteU32(0x5F0F3CF5) || | |
128 !out->WriteU16(file->head->flags) || | |
129 !out->WriteU16(file->head->ppem) || | |
130 !out->WriteR64(file->head->created) || | |
131 !out->WriteR64(file->head->modified) || | |
132 !out->WriteS16(file->head->xmin) || | |
133 !out->WriteS16(file->head->ymin) || | |
134 !out->WriteS16(file->head->xmax) || | |
135 !out->WriteS16(file->head->ymax) || | |
136 !out->WriteU16(file->head->mac_style) || | |
137 !out->WriteU16(file->head->min_ppem) || | |
138 !out->WriteS16(2) || | |
139 !out->WriteS16(file->head->index_to_loc_format) || | |
140 !out->WriteS16(0)) { | |
141 return OTS_FAILURE_MSG("Failed to write head table"); | |
142 } | |
143 | |
144 return true; | |
145 } | |
146 | |
147 void ots_head_free(OpenTypeFile *file) { | |
148 delete file->head; | |
149 } | |
150 | |
151 } // namespace | |
152 | |
153 #undef TABLE_NAME | |
OLD | NEW |