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.
10 // http://www.microsoft.com/typography/otspec/head.htm
14 bool OpenTypeHEAD::Parse(const uint8_t *data
, size_t length
) {
15 Buffer
table(data
, length
);
18 if (!table
.ReadU32(&version
) ||
19 !table
.ReadU32(&this->revision
)) {
20 return Error("Failed to read table header");
23 if (version
>> 16 != 1) {
24 return Error("Unsupported majorVersion: %d", version
>> 16);
27 // Skip the checksum adjustment
29 return Error("Failed to read checksum");
33 if (!table
.ReadU32(&magic
) || magic
!= 0x5F0F3CF5) {
34 return Error("Failed to read or incorrect magicNumber");
37 if (!table
.ReadU16(&this->flags
)) {
38 return Error("Failed to read flags");
41 // We allow bits 0..4, 11..13
42 this->flags
&= 0x381f;
44 if (!table
.ReadU16(&this->upem
)) {
45 return Error("Failed to read unitsPerEm");
48 // upem must be in range
49 if (this->upem
< 16 ||
51 return Error("unitsPerEm on in the range [16, 16384]: %d", this->upem
);
54 if (!table
.ReadR64(&this->created
) ||
55 !table
.ReadR64(&this->modified
)) {
56 return Error("Can't read font dates");
59 if (!table
.ReadS16(&this->xmin
) ||
60 !table
.ReadS16(&this->ymin
) ||
61 !table
.ReadS16(&this->xmax
) ||
62 !table
.ReadS16(&this->ymax
)) {
63 return Error("Failed to read font bounding box");
66 if (this->xmin
> this->xmax
) {
67 return Error("Bad x dimension in the font bounding box (%d, %d)",
68 this->xmin
, this->xmax
);
70 if (this->ymin
> this->ymax
) {
71 return Error("Bad y dimension in the font bounding box (%d, %d)",
72 this->ymin
, this->ymax
);
75 if (!table
.ReadU16(&this->mac_style
)) {
76 return Error("Failed to read macStyle");
80 this->mac_style
&= 0x7f;
82 if (!table
.ReadU16(&this->min_ppem
)) {
83 return Error("Failed to read lowestRecPPEM");
86 // We don't care about the font direction hint
88 return Error("Failed to read fontDirectionHint");
91 if (!table
.ReadS16(&this->index_to_loc_format
)) {
92 return Error("Failed to read indexToLocFormat");
94 if (this->index_to_loc_format
< 0 ||
95 this->index_to_loc_format
> 1) {
96 return Error("Bad indexToLocFormat %d", this->index_to_loc_format
);
99 int16_t glyph_data_format
;
100 if (!table
.ReadS16(&glyph_data_format
) ||
102 return Error("Failed to read or bad glyphDataFormat");
108 bool OpenTypeHEAD::Serialize(OTSStream
*out
) {
109 if (!out
->WriteU32(0x00010000) ||
110 !out
->WriteU32(this->revision
) ||
111 !out
->WriteU32(0) || // check sum not filled in yet
112 !out
->WriteU32(0x5F0F3CF5) ||
113 !out
->WriteU16(this->flags
) ||
114 !out
->WriteU16(this->upem
) ||
115 !out
->WriteR64(this->created
) ||
116 !out
->WriteR64(this->modified
) ||
117 !out
->WriteS16(this->xmin
) ||
118 !out
->WriteS16(this->ymin
) ||
119 !out
->WriteS16(this->xmax
) ||
120 !out
->WriteS16(this->ymax
) ||
121 !out
->WriteU16(this->mac_style
) ||
122 !out
->WriteU16(this->min_ppem
) ||
124 !out
->WriteS16(this->index_to_loc_format
) ||
126 return Error("Failed to write table");