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 "maxp.h"
6
7// maxp - Maximum Profile
8// http://www.microsoft.com/opentype/otspec/maxp.htm
9
10namespace ots {
11
12bool ots_maxp_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
13  Buffer table(data, length);
14
15  OpenTypeMAXP *maxp = new OpenTypeMAXP;
16  file->maxp = maxp;
17
18  uint32_t version = 0;
19  if (!table.ReadU32(&version)) {
20    return OTS_FAILURE();
21  }
22
23  if (version >> 16 > 1) {
24    return OTS_FAILURE();
25  }
26
27  if (!table.ReadU16(&maxp->num_glyphs)) {
28    return OTS_FAILURE();
29  }
30
31  if (!maxp->num_glyphs) {
32    return OTS_FAILURE();
33  }
34
35  if (version >> 16 == 1) {
36    maxp->version_1 = true;
37    if (!table.ReadU16(&maxp->max_points) ||
38        !table.ReadU16(&maxp->max_contours) ||
39        !table.ReadU16(&maxp->max_c_points) ||
40        !table.ReadU16(&maxp->max_c_contours) ||
41        !table.ReadU16(&maxp->max_zones) ||
42        !table.ReadU16(&maxp->max_t_points) ||
43        !table.ReadU16(&maxp->max_storage) ||
44        !table.ReadU16(&maxp->max_fdefs) ||
45        !table.ReadU16(&maxp->max_idefs) ||
46        !table.ReadU16(&maxp->max_stack) ||
47        !table.ReadU16(&maxp->max_size_glyf_instructions) ||
48        !table.ReadU16(&maxp->max_c_components) ||
49        !table.ReadU16(&maxp->max_c_depth)) {
50      return OTS_FAILURE();
51    }
52
53    if (maxp->max_zones == 0) {
54      // workaround for ipa*.ttf Japanese fonts.
55      OTS_WARNING("bad max_zones: %u", maxp->max_zones);
56      maxp->max_zones = 1;
57    } else if (maxp->max_zones == 3) {
58      // workaround for Ecolier-*.ttf fonts.
59      OTS_WARNING("bad max_zones: %u", maxp->max_zones);
60      maxp->max_zones = 2;
61    }
62
63    if ((maxp->max_zones != 1) && (maxp->max_zones != 2)) {
64      return OTS_FAILURE();
65    }
66  } else {
67    maxp->version_1 = false;
68  }
69
70  return true;
71}
72
73bool ots_maxp_should_serialise(OpenTypeFile *file) {
74  return file->maxp != NULL;
75}
76
77bool ots_maxp_serialise(OTSStream *out, OpenTypeFile *file) {
78  const OpenTypeMAXP *maxp = file->maxp;
79
80  if (!out->WriteU32(maxp->version_1 ? 0x00010000 : 0x00005000) ||
81      !out->WriteU16(maxp->num_glyphs)) {
82    return OTS_FAILURE();
83  }
84
85  if (!maxp->version_1) return true;
86
87  if (!out->WriteU16(maxp->max_points) ||
88      !out->WriteU16(maxp->max_contours) ||
89      !out->WriteU16(maxp->max_c_points) ||
90      !out->WriteU16(maxp->max_c_contours)) {
91    return OTS_FAILURE();
92  }
93
94  if (g_transcode_hints) {
95    if (!out->WriteU16(maxp->max_zones) ||
96        !out->WriteU16(maxp->max_t_points) ||
97        !out->WriteU16(maxp->max_storage) ||
98        !out->WriteU16(maxp->max_fdefs) ||
99        !out->WriteU16(maxp->max_idefs) ||
100        !out->WriteU16(maxp->max_stack) ||
101        !out->WriteU16(maxp->max_size_glyf_instructions)) {
102      return OTS_FAILURE();
103    }
104  } else {
105    if (!out->WriteU16(1) ||  // max zones
106        !out->WriteU16(0) ||  // max twilight points
107        !out->WriteU16(0) ||  // max storage
108        !out->WriteU16(0) ||  // max function defs
109        !out->WriteU16(0) ||  // max instruction defs
110        !out->WriteU16(0) ||  // max stack elements
111        !out->WriteU16(0)) {  // max instruction byte count
112      return OTS_FAILURE();
113    }
114  }
115
116  if (!out->WriteU16(maxp->max_c_components) ||
117      !out->WriteU16(maxp->max_c_depth)) {
118    return OTS_FAILURE();
119  }
120
121  return true;
122}
123
124void ots_maxp_free(OpenTypeFile *file) {
125  delete file->maxp;
126}
127
128}  // namespace ots
129