Home | History | Annotate | Download | only in src
      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 "head.h"
      6 
      7 #include <cstring>
      8 
      9 // head - Font Header
     10 // http://www.microsoft.com/opentype/otspec/head.htm
     11 
     12 namespace ots {
     13 
     14 bool ots_head_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
     15   Buffer table(data, length);
     16   file->head = new OpenTypeHEAD;
     17 
     18   uint32_t version = 0;
     19   if (!table.ReadU32(&version) ||
     20       !table.ReadU32(&file->head->revision)) {
     21     return OTS_FAILURE();
     22   }
     23 
     24   if (version >> 16 != 1) {
     25     return OTS_FAILURE();
     26   }
     27 
     28   // Skip the checksum adjustment
     29   if (!table.Skip(4)) {
     30     return OTS_FAILURE();
     31   }
     32 
     33   uint32_t magic;
     34   if (!table.ReadTag(&magic) ||
     35       std::memcmp(&magic, "\x5F\x0F\x3C\xF5", 4)) {
     36     return OTS_FAILURE();
     37   }
     38 
     39   if (!table.ReadU16(&file->head->flags)) {
     40     return OTS_FAILURE();
     41   }
     42 
     43   // We allow bits 0..4, 11..13
     44   file->head->flags &= 0x381f;
     45 
     46   if (!table.ReadU16(&file->head->ppem)) {
     47     return OTS_FAILURE();
     48   }
     49 
     50   // ppem must be in range
     51   if (file->head->ppem < 16 ||
     52       file->head->ppem > 16384) {
     53     return OTS_FAILURE();
     54   }
     55 
     56   // ppem must be a power of two
     57 #if 0
     58   // We don't call ots_failure() for now since lots of TrueType fonts are
     59   // not following this rule. Putting OTS_WARNING here is too noisy.
     60   if ((file->head->ppem - 1) & file->head->ppem) {
     61     return OTS_FAILURE();
     62   }
     63 #endif
     64 
     65   if (!table.ReadR64(&file->head->created) ||
     66       !table.ReadR64(&file->head->modified)) {
     67     return OTS_FAILURE();
     68   }
     69 
     70   if (!table.ReadS16(&file->head->xmin) ||
     71       !table.ReadS16(&file->head->ymin) ||
     72       !table.ReadS16(&file->head->xmax) ||
     73       !table.ReadS16(&file->head->ymax)) {
     74     return OTS_FAILURE();
     75   }
     76 
     77   if (file->head->xmin > file->head->xmax) {
     78     return OTS_FAILURE();
     79   }
     80   if (file->head->ymin > file->head->ymax) {
     81     return OTS_FAILURE();
     82   }
     83 
     84   if (!table.ReadU16(&file->head->mac_style)) {
     85     return OTS_FAILURE();
     86   }
     87 
     88   // We allow bits 0..6
     89   file->head->mac_style &= 0x7f;
     90 
     91   if (!table.ReadU16(&file->head->min_ppem)) {
     92     return OTS_FAILURE();
     93   }
     94 
     95   // We don't care about the font direction hint
     96   if (!table.Skip(2)) {
     97     return OTS_FAILURE();
     98   }
     99 
    100   if (!table.ReadS16(&file->head->index_to_loc_format)) {
    101     return OTS_FAILURE();
    102   }
    103   if (file->head->index_to_loc_format < 0 ||
    104       file->head->index_to_loc_format > 1) {
    105     return OTS_FAILURE();
    106   }
    107 
    108   int16_t glyph_data_format;
    109   if (!table.ReadS16(&glyph_data_format) ||
    110       glyph_data_format) {
    111     return OTS_FAILURE();
    112   }
    113 
    114   return true;
    115 }
    116 
    117 bool ots_head_should_serialise(OpenTypeFile *file) {
    118   return file->head != NULL;
    119 }
    120 
    121 bool ots_head_serialise(OTSStream *out, OpenTypeFile *file) {
    122   if (!out->WriteU32(0x00010000) ||
    123       !out->WriteU32(file->head->revision) ||
    124       !out->WriteU32(0) ||  // check sum not filled in yet
    125       !out->WriteU32(0x5F0F3CF5) ||
    126       !out->WriteU16(file->head->flags) ||
    127       !out->WriteU16(file->head->ppem) ||
    128       !out->WriteR64(file->head->created) ||
    129       !out->WriteR64(file->head->modified) ||
    130       !out->WriteS16(file->head->xmin) ||
    131       !out->WriteS16(file->head->ymin) ||
    132       !out->WriteS16(file->head->xmax) ||
    133       !out->WriteS16(file->head->ymax) ||
    134       !out->WriteU16(file->head->mac_style) ||
    135       !out->WriteU16(file->head->min_ppem) ||
    136       !out->WriteS16(2) ||
    137       !out->WriteS16(file->head->index_to_loc_format) ||
    138       !out->WriteS16(0)) {
    139     return OTS_FAILURE();
    140   }
    141 
    142   return true;
    143 }
    144 
    145 void ots_head_free(OpenTypeFile *file) {
    146   delete file->head;
    147 }
    148 
    149 }  // namespace
    150