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(Font
* font
, const uint8_t *data
, size_t length
) {
17 Buffer
table(data
, length
);
18 OpenTypeHEAD
*head
= new OpenTypeHEAD
;
22 if (!table
.ReadU32(&version
) ||
23 !table
.ReadU32(&head
->revision
)) {
24 return OTS_FAILURE_MSG("Failed to read head header");
27 if (version
>> 16 != 1) {
28 return OTS_FAILURE_MSG("Bad head table version of %d", version
);
31 // Skip the checksum adjustment
33 return OTS_FAILURE_MSG("Failed to read checksum");
37 if (!table
.ReadU32(&magic
) || magic
!= 0x5F0F3CF5) {
38 return OTS_FAILURE_MSG("Failed to read font magic number");
41 if (!table
.ReadU16(&head
->flags
)) {
42 return OTS_FAILURE_MSG("Failed to read head flags");
45 // We allow bits 0..4, 11..13
46 head
->flags
&= 0x381f;
48 if (!table
.ReadU16(&head
->ppem
)) {
49 return OTS_FAILURE_MSG("Failed to read pixels per em");
52 // ppem must be in range
53 if (head
->ppem
< 16 ||
55 return OTS_FAILURE_MSG("Bad ppm of %d", 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 ((head
->ppem
- 1) & head
->ppem
) {
63 return OTS_FAILURE_MSG("ppm not a power of two: %d", head
->ppem
);
67 if (!table
.ReadR64(&head
->created
) ||
68 !table
.ReadR64(&head
->modified
)) {
69 return OTS_FAILURE_MSG("Can't read font dates");
72 if (!table
.ReadS16(&head
->xmin
) ||
73 !table
.ReadS16(&head
->ymin
) ||
74 !table
.ReadS16(&head
->xmax
) ||
75 !table
.ReadS16(&head
->ymax
)) {
76 return OTS_FAILURE_MSG("Failed to read font bounding box");
79 if (head
->xmin
> head
->xmax
) {
80 return OTS_FAILURE_MSG("Bad x dimension in the font bounding box (%d, %d)", head
->xmin
, head
->xmax
);
82 if (head
->ymin
> head
->ymax
) {
83 return OTS_FAILURE_MSG("Bad y dimension in the font bounding box (%d, %d)", head
->ymin
, head
->ymax
);
86 if (!table
.ReadU16(&head
->mac_style
)) {
87 return OTS_FAILURE_MSG("Failed to read font style");
91 head
->mac_style
&= 0x7f;
93 if (!table
.ReadU16(&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(&head
->index_to_loc_format
)) {
103 return OTS_FAILURE_MSG("Failed to read index to loc format");
105 if (head
->index_to_loc_format
< 0 ||
106 head
->index_to_loc_format
> 1) {
107 return OTS_FAILURE_MSG("Bad index to loc format %d", 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(Font
*font
) {
120 return font
->head
!= NULL
;
123 bool ots_head_serialise(OTSStream
*out
, Font
*font
) {
124 const OpenTypeHEAD
*head
= font
->head
;
125 if (!out
->WriteU32(0x00010000) ||
126 !out
->WriteU32(head
->revision
) ||
127 !out
->WriteU32(0) || // check sum not filled in yet
128 !out
->WriteU32(0x5F0F3CF5) ||
129 !out
->WriteU16(head
->flags
) ||
130 !out
->WriteU16(head
->ppem
) ||
131 !out
->WriteR64(head
->created
) ||
132 !out
->WriteR64(head
->modified
) ||
133 !out
->WriteS16(head
->xmin
) ||
134 !out
->WriteS16(head
->ymin
) ||
135 !out
->WriteS16(head
->xmax
) ||
136 !out
->WriteS16(head
->ymax
) ||
137 !out
->WriteU16(head
->mac_style
) ||
138 !out
->WriteU16(head
->min_ppem
) ||
140 !out
->WriteS16(head
->index_to_loc_format
) ||
142 return OTS_FAILURE_MSG("Failed to write head table");
148 void ots_head_reuse(Font
*font
, Font
*other
) {
149 font
->head
= other
->head
;
150 font
->head_reused
= true;
153 void ots_head_free(Font
*font
) {