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 "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 13 namespace ots { 14 15 bool 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) { 38 uint16_t offset = 0; 39 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) { 50 uint32_t offset = 0; 51 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 65 bool ots_loca_should_serialise(OpenTypeFile *file) { 66 return file->loca != NULL; 67 } 68 69 bool 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 94 void ots_loca_free(OpenTypeFile *file) { 95 delete file->loca; 96 } 97 98 } // namespace ots 99