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