michael@0: // Copyright (c) 2009 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "loca.h" michael@0: michael@0: #include "head.h" michael@0: #include "maxp.h" michael@0: michael@0: // loca - Index to Location michael@0: // http://www.microsoft.com/typography/otspec/loca.htm michael@0: michael@0: #define TABLE_NAME "loca" michael@0: michael@0: namespace ots { michael@0: michael@0: bool ots_loca_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { michael@0: Buffer table(data, length); michael@0: michael@0: // We can't do anything useful in validating this data except to ensure that michael@0: // the values are monotonically increasing. michael@0: michael@0: OpenTypeLOCA *loca = new OpenTypeLOCA; michael@0: file->loca = loca; michael@0: michael@0: if (!file->maxp || !file->head) { michael@0: return OTS_FAILURE_MSG("maxp or head tables missing from font, needed by loca"); michael@0: } michael@0: michael@0: const unsigned num_glyphs = file->maxp->num_glyphs; michael@0: unsigned last_offset = 0; michael@0: loca->offsets.resize(num_glyphs + 1); michael@0: // maxp->num_glyphs is uint16_t, thus the addition never overflows. michael@0: michael@0: if (file->head->index_to_loc_format == 0) { michael@0: // Note that the <= here (and below) is correct. There is one more offset michael@0: // than the number of glyphs in order to give the length of the final michael@0: // glyph. michael@0: for (unsigned i = 0; i <= num_glyphs; ++i) { michael@0: uint16_t offset = 0; michael@0: if (!table.ReadU16(&offset)) { michael@0: return OTS_FAILURE_MSG("Failed to read offset for glyph %d", i); michael@0: } michael@0: if (offset < last_offset) { michael@0: return OTS_FAILURE_MSG("Out of order offset %d < %d for glyph %d", offset, last_offset, i); michael@0: } michael@0: last_offset = offset; michael@0: loca->offsets[i] = offset * 2; michael@0: } michael@0: } else { michael@0: for (unsigned i = 0; i <= num_glyphs; ++i) { michael@0: uint32_t offset = 0; michael@0: if (!table.ReadU32(&offset)) { michael@0: return OTS_FAILURE_MSG("Failed to read offset for glyph %d", i); michael@0: } michael@0: if (offset < last_offset) { michael@0: return OTS_FAILURE_MSG("Out of order offset %d < %d for glyph %d", offset, last_offset, i); michael@0: } michael@0: last_offset = offset; michael@0: loca->offsets[i] = offset; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool ots_loca_should_serialise(OpenTypeFile *file) { michael@0: return file->loca != NULL; michael@0: } michael@0: michael@0: bool ots_loca_serialise(OTSStream *out, OpenTypeFile *file) { michael@0: const OpenTypeLOCA *loca = file->loca; michael@0: const OpenTypeHEAD *head = file->head; michael@0: michael@0: if (!head) { michael@0: return OTS_FAILURE_MSG("Missing head table in font needed by loca"); michael@0: } michael@0: michael@0: if (head->index_to_loc_format == 0) { michael@0: for (unsigned i = 0; i < loca->offsets.size(); ++i) { michael@0: if (!out->WriteU16(loca->offsets[i] >> 1)) { michael@0: return OTS_FAILURE_MSG("Failed to write glyph offset for glyph %d", i); michael@0: } michael@0: } michael@0: } else { michael@0: for (unsigned i = 0; i < loca->offsets.size(); ++i) { michael@0: if (!out->WriteU32(loca->offsets[i])) { michael@0: return OTS_FAILURE_MSG("Failed to write glyph offset for glyph %d", i); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void ots_loca_free(OpenTypeFile *file) { michael@0: delete file->loca; michael@0: } michael@0: michael@0: } // namespace ots