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