1d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Use of this source code is governed by a BSD-style license that can be
3d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// found in the LICENSE file.
4d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
5d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "loca.h"
6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "head.h"
8d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "maxp.h"
9d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// loca - Index to Location
11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// http://www.microsoft.com/opentype/otspec/loca.htm
12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgnamespace ots {
14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_loca_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  Buffer table(data, length);
17d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
18d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  // We can't do anything useful in validating this data except to ensure that
19d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  // the values are monotonically increasing.
20d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
21d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  OpenTypeLOCA *loca = new OpenTypeLOCA;
22d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  file->loca = loca;
23d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
24d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  if (!file->maxp || !file->head) {
25d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return OTS_FAILURE();
26d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
27d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
28d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  const unsigned num_glyphs = file->maxp->num_glyphs;
29d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  unsigned last_offset = 0;
30d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  loca->offsets.resize(num_glyphs + 1);
31d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  // maxp->num_glyphs is uint16_t, thus the addition never overflows.
32d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
33d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  if (file->head->index_to_loc_format == 0) {
34d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    // Note that the <= here (and below) is correct. There is one more offset
35d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    // than the number of glyphs in order to give the length of the final
36d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    // glyph.
37d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    for (unsigned i = 0; i <= num_glyphs; ++i) {
388ad0a175fe440054932dd25ae9b4b1867e66d387yusukes@chromium.org      uint16_t offset = 0;
39d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!table.ReadU16(&offset)) {
40d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
41d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
42d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (offset < last_offset) {
43d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
44d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
45d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      last_offset = offset;
46d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      loca->offsets[i] = offset * 2;
47d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
48d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  } else {
49d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    for (unsigned i = 0; i <= num_glyphs; ++i) {
508ad0a175fe440054932dd25ae9b4b1867e66d387yusukes@chromium.org      uint32_t offset = 0;
51d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!table.ReadU32(&offset)) {
52d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
53d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
54d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (offset < last_offset) {
55d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
56d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
57d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      last_offset = offset;
58d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      loca->offsets[i] = offset;
59d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
60d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
61d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
62d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  return true;
63d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}
64d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
65d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_loca_should_serialise(OpenTypeFile *file) {
662beaf1d97c4ba6d953462003db9ddb104b53d196agl@chromium.org  return file->loca != NULL;
67d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}
68d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
69d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_loca_serialise(OTSStream *out, OpenTypeFile *file) {
70d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  const OpenTypeLOCA *loca = file->loca;
71d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  const OpenTypeHEAD *head = file->head;
72d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
73d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  if (!head) {
74d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return OTS_FAILURE();
75d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
76d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
77d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  if (head->index_to_loc_format == 0) {
78d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    for (unsigned i = 0; i < loca->offsets.size(); ++i) {
79d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!out->WriteU16(loca->offsets[i] >> 1)) {
80d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
81d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
82d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
83d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  } else {
84d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    for (unsigned i = 0; i < loca->offsets.size(); ++i) {
85d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      if (!out->WriteU32(loca->offsets[i])) {
86d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        return OTS_FAILURE();
87d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      }
88d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
89d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
90d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
91d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  return true;
92d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}
93d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
94d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgvoid ots_loca_free(OpenTypeFile *file) {
95d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  delete file->loca;
96d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}
97d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
98d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}  // namespace ots
99