Line data Source code
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 0 : bool ots_head_parse(Font* font, const uint8_t *data, size_t length) {
17 0 : Buffer table(data, length);
18 0 : OpenTypeHEAD *head = new OpenTypeHEAD;
19 0 : font->head = head;
20 :
21 0 : uint32_t version = 0;
22 0 : if (!table.ReadU32(&version) ||
23 0 : !table.ReadU32(&head->revision)) {
24 0 : return OTS_FAILURE_MSG("Failed to read head header");
25 : }
26 :
27 0 : if (version >> 16 != 1) {
28 0 : return OTS_FAILURE_MSG("Bad head table version of %d", version);
29 : }
30 :
31 : // Skip the checksum adjustment
32 0 : if (!table.Skip(4)) {
33 0 : return OTS_FAILURE_MSG("Failed to read checksum");
34 : }
35 :
36 : uint32_t magic;
37 0 : if (!table.ReadU32(&magic) || magic != 0x5F0F3CF5) {
38 0 : return OTS_FAILURE_MSG("Failed to read font magic number");
39 : }
40 :
41 0 : if (!table.ReadU16(&head->flags)) {
42 0 : return OTS_FAILURE_MSG("Failed to read head flags");
43 : }
44 :
45 : // We allow bits 0..4, 11..13
46 0 : head->flags &= 0x381f;
47 :
48 0 : if (!table.ReadU16(&head->ppem)) {
49 0 : return OTS_FAILURE_MSG("Failed to read pixels per em");
50 : }
51 :
52 : // ppem must be in range
53 0 : if (head->ppem < 16 ||
54 0 : head->ppem > 16384) {
55 0 : return OTS_FAILURE_MSG("Bad ppm of %d", 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 ((head->ppem - 1) & head->ppem) {
63 : return OTS_FAILURE_MSG("ppm not a power of two: %d", head->ppem);
64 : }
65 : #endif
66 :
67 0 : if (!table.ReadR64(&head->created) ||
68 0 : !table.ReadR64(&head->modified)) {
69 0 : return OTS_FAILURE_MSG("Can't read font dates");
70 : }
71 :
72 0 : if (!table.ReadS16(&head->xmin) ||
73 0 : !table.ReadS16(&head->ymin) ||
74 0 : !table.ReadS16(&head->xmax) ||
75 0 : !table.ReadS16(&head->ymax)) {
76 0 : return OTS_FAILURE_MSG("Failed to read font bounding box");
77 : }
78 :
79 0 : if (head->xmin > head->xmax) {
80 0 : return OTS_FAILURE_MSG("Bad x dimension in the font bounding box (%d, %d)", head->xmin, head->xmax);
81 : }
82 0 : if (head->ymin > head->ymax) {
83 0 : return OTS_FAILURE_MSG("Bad y dimension in the font bounding box (%d, %d)", head->ymin, head->ymax);
84 : }
85 :
86 0 : if (!table.ReadU16(&head->mac_style)) {
87 0 : return OTS_FAILURE_MSG("Failed to read font style");
88 : }
89 :
90 : // We allow bits 0..6
91 0 : head->mac_style &= 0x7f;
92 :
93 0 : if (!table.ReadU16(&head->min_ppem)) {
94 0 : return OTS_FAILURE_MSG("Failed to read font minimum ppm");
95 : }
96 :
97 : // We don't care about the font direction hint
98 0 : if (!table.Skip(2)) {
99 0 : return OTS_FAILURE_MSG("Failed to skip font direction hint");
100 : }
101 :
102 0 : if (!table.ReadS16(&head->index_to_loc_format)) {
103 0 : return OTS_FAILURE_MSG("Failed to read index to loc format");
104 : }
105 0 : if (head->index_to_loc_format < 0 ||
106 0 : head->index_to_loc_format > 1) {
107 0 : return OTS_FAILURE_MSG("Bad index to loc format %d", head->index_to_loc_format);
108 : }
109 :
110 : int16_t glyph_data_format;
111 0 : if (!table.ReadS16(&glyph_data_format) ||
112 0 : glyph_data_format) {
113 0 : return OTS_FAILURE_MSG("Failed to read glyph data format");
114 : }
115 :
116 0 : return true;
117 : }
118 :
119 0 : bool ots_head_should_serialise(Font *font) {
120 0 : return font->head != NULL;
121 : }
122 :
123 0 : bool ots_head_serialise(OTSStream *out, Font *font) {
124 0 : const OpenTypeHEAD *head = font->head;
125 0 : if (!out->WriteU32(0x00010000) ||
126 0 : !out->WriteU32(head->revision) ||
127 0 : !out->WriteU32(0) || // check sum not filled in yet
128 0 : !out->WriteU32(0x5F0F3CF5) ||
129 0 : !out->WriteU16(head->flags) ||
130 0 : !out->WriteU16(head->ppem) ||
131 0 : !out->WriteR64(head->created) ||
132 0 : !out->WriteR64(head->modified) ||
133 0 : !out->WriteS16(head->xmin) ||
134 0 : !out->WriteS16(head->ymin) ||
135 0 : !out->WriteS16(head->xmax) ||
136 0 : !out->WriteS16(head->ymax) ||
137 0 : !out->WriteU16(head->mac_style) ||
138 0 : !out->WriteU16(head->min_ppem) ||
139 0 : !out->WriteS16(2) ||
140 0 : !out->WriteS16(head->index_to_loc_format) ||
141 0 : !out->WriteS16(0)) {
142 0 : return OTS_FAILURE_MSG("Failed to write head table");
143 : }
144 :
145 0 : return true;
146 : }
147 :
148 0 : void ots_head_reuse(Font *font, Font *other) {
149 0 : font->head = other->head;
150 0 : font->head_reused = true;
151 0 : }
152 :
153 0 : void ots_head_free(Font *font) {
154 0 : delete font->head;
155 0 : }
156 :
157 : } // namespace
158 :
159 : #undef TABLE_NAME
|