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.
10 // http://www.microsoft.com/typography/otspec/head.htm
12 #define TABLE_NAME "head"
16 bool ots_head_parse(OpenTypeFile
*file
, const uint8_t *data
, size_t length
) {
17 Buffer
table(data
, length
);
18 file
->head
= new OpenTypeHEAD
;
21 if (!table
.ReadU32(&version
) ||
22 !table
.ReadU32(&file
->head
->revision
)) {
23 return OTS_FAILURE_MSG("Failed to read head header");
26 if (version
>> 16 != 1) {
27 return OTS_FAILURE_MSG("Bad head table version of %d", version
);
30 // Skip the checksum adjustment
32 return OTS_FAILURE_MSG("Failed to read checksum");
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");
41 if (!table
.ReadU16(&file
->head
->flags
)) {
42 return OTS_FAILURE_MSG("Failed to read head flags");
45 // We allow bits 0..4, 11..13
46 file
->head
->flags
&= 0x381f;
48 if (!table
.ReadU16(&file
->head
->ppem
)) {
49 return OTS_FAILURE_MSG("Failed to read pixels per em");
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
);
58 // ppem must be a power of two
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
);
67 if (!table
.ReadR64(&file
->head
->created
) ||
68 !table
.ReadR64(&file
->head
->modified
)) {
69 return OTS_FAILURE_MSG("Can't read font dates");
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");
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
);
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
);
86 if (!table
.ReadU16(&file
->head
->mac_style
)) {
87 return OTS_FAILURE_MSG("Failed to read font style");
91 file
->head
->mac_style
&= 0x7f;
93 if (!table
.ReadU16(&file
->head
->min_ppem
)) {
94 return OTS_FAILURE_MSG("Failed to read font minimum ppm");
97 // We don't care about the font direction hint
99 return OTS_FAILURE_MSG("Failed to skip font direction hint");
102 if (!table
.ReadS16(&file
->head
->index_to_loc_format
)) {
103 return OTS_FAILURE_MSG("Failed to read index to loc format");
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_loc_format
);
110 int16_t glyph_data_format
;
111 if (!table
.ReadS16(&glyph_data_format
) ||
113 return OTS_FAILURE_MSG("Failed to read glyph data format");
119 bool ots_head_should_serialise(OpenTypeFile
*file
) {
120 return file
->head
!= NULL
;
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
) ||
139 !out
->WriteS16(file
->head
->index_to_loc_format
) ||
141 return OTS_FAILURE_MSG("Failed to write head table");
147 void ots_head_free(OpenTypeFile
*file
) {