blob: a2947b279922992712e316d478916196e1d033a1 [file] [log] [blame]
yusukes@chromium.orgd257d182009-11-04 04:56:32 +00001// 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 "loca.h"
6
7#include "head.h"
8#include "maxp.h"
9
10// loca - Index to Location
11// http://www.microsoft.com/opentype/otspec/loca.htm
12
13namespace ots {
14
15bool ots_loca_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
16 Buffer table(data, length);
17
18 // We can't do anything useful in validating this data except to ensure that
19 // the values are monotonically increasing.
20
21 OpenTypeLOCA *loca = new OpenTypeLOCA;
22 file->loca = loca;
23
24 if (!file->maxp || !file->head) {
25 return OTS_FAILURE();
26 }
27
28 const unsigned num_glyphs = file->maxp->num_glyphs;
29 unsigned last_offset = 0;
30 loca->offsets.resize(num_glyphs + 1);
31 // maxp->num_glyphs is uint16_t, thus the addition never overflows.
32
33 if (file->head->index_to_loc_format == 0) {
34 // Note that the <= here (and below) is correct. There is one more offset
35 // than the number of glyphs in order to give the length of the final
36 // glyph.
37 for (unsigned i = 0; i <= num_glyphs; ++i) {
yusukes@chromium.org8ad0a172009-11-04 06:07:58 +000038 uint16_t offset = 0;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000039 if (!table.ReadU16(&offset)) {
40 return OTS_FAILURE();
41 }
42 if (offset < last_offset) {
43 return OTS_FAILURE();
44 }
45 last_offset = offset;
46 loca->offsets[i] = offset * 2;
47 }
48 } else {
49 for (unsigned i = 0; i <= num_glyphs; ++i) {
yusukes@chromium.org8ad0a172009-11-04 06:07:58 +000050 uint32_t offset = 0;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000051 if (!table.ReadU32(&offset)) {
52 return OTS_FAILURE();
53 }
54 if (offset < last_offset) {
55 return OTS_FAILURE();
56 }
57 last_offset = offset;
58 loca->offsets[i] = offset;
59 }
60 }
61
62 return true;
63}
64
65bool ots_loca_should_serialise(OpenTypeFile *file) {
agl@chromium.org2beaf1d2011-01-21 17:19:34 +000066 return file->loca != NULL;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000067}
68
69bool ots_loca_serialise(OTSStream *out, OpenTypeFile *file) {
70 const OpenTypeLOCA *loca = file->loca;
71 const OpenTypeHEAD *head = file->head;
72
73 if (!head) {
74 return OTS_FAILURE();
75 }
76
77 if (head->index_to_loc_format == 0) {
78 for (unsigned i = 0; i < loca->offsets.size(); ++i) {
79 if (!out->WriteU16(loca->offsets[i] >> 1)) {
80 return OTS_FAILURE();
81 }
82 }
83 } else {
84 for (unsigned i = 0; i < loca->offsets.size(); ++i) {
85 if (!out->WriteU32(loca->offsets[i])) {
86 return OTS_FAILURE();
87 }
88 }
89 }
90
91 return true;
92}
93
94void ots_loca_free(OpenTypeFile *file) {
95 delete file->loca;
96}
97
98} // namespace ots