1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 /*
  31  * Copyright © 2007,2008,2009  Red Hat, Inc.
  32  * Copyright © 2012  Google, Inc.
  33  *
  34  *  This is part of HarfBuzz, a text shaping library.
  35  *
  36  * Permission is hereby granted, without written agreement and without
  37  * license or royalty fees, to use, copy, modify, and distribute this
  38  * software and its documentation for any purpose, provided that the
  39  * above copyright notice and the following two paragraphs appear in
  40  * all copies of this software.
  41  *
  42  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  43  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  44  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  45  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  46  * DAMAGE.
  47  *
  48  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  49  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  50  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  51  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  52  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  53  *
  54  * Red Hat Author(s): Behdad Esfahbod
  55  * Google Author(s): Behdad Esfahbod
  56  */
  57 
  58 #ifndef HB_OPEN_FILE_PRIVATE_HH
  59 #define HB_OPEN_FILE_PRIVATE_HH
  60 
  61 #include "hb-open-type-private.hh"
  62 
  63 
  64 namespace OT {
  65 
  66 
  67 /*
  68  *
  69  * The OpenType Font File
  70  *
  71  */
  72 
  73 
  74 /*
  75  * Organization of an OpenType Font
  76  */
  77 
  78 struct OpenTypeFontFile;
  79 struct OffsetTable;
  80 struct TTCHeader;
  81 
  82 
  83 typedef struct TableRecord
  84 {
  85   inline bool sanitize (hb_sanitize_context_t *c) const
  86   {
  87     TRACE_SANITIZE (this);
  88     return_trace (c->check_struct (this));
  89   }
  90 
  91   Tag           tag;            /* 4-byte identifier. */
  92   CheckSum      checkSum;       /* CheckSum for this table. */
  93   ULONG         offset;         /* Offset from beginning of TrueType font
  94                                  * file. */
  95   ULONG         length;         /* Length of this table. */
  96   public:
  97   DEFINE_SIZE_STATIC (16);
  98 } OpenTypeTable;
  99 
 100 typedef struct OffsetTable
 101 {
 102   friend struct OpenTypeFontFile;
 103 
 104   inline unsigned int get_table_count (void) const
 105   { return numTables; }
 106   inline const TableRecord& get_table (unsigned int i) const
 107   {
 108     if (unlikely (i >= numTables)) return Null(TableRecord);
 109     return tables[i];
 110   }
 111   inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
 112   {
 113     Tag t;
 114     t.set (tag);
 115     unsigned int count = numTables;
 116     for (unsigned int i = 0; i < count; i++)
 117     {
 118       if (t == tables[i].tag)
 119       {
 120         if (table_index) *table_index = i;
 121         return true;
 122       }
 123     }
 124     if (table_index) *table_index = Index::NOT_FOUND_INDEX;
 125     return false;
 126   }
 127   inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
 128   {
 129     unsigned int table_index;
 130     find_table_index (tag, &table_index);
 131     return get_table (table_index);
 132   }
 133 
 134   public:
 135   inline bool sanitize (hb_sanitize_context_t *c) const
 136   {
 137     TRACE_SANITIZE (this);
 138     return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
 139   }
 140 
 141   protected:
 142   Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
 143   USHORT        numTables;      /* Number of tables. */
 144   USHORT        searchRangeZ;   /* (Maximum power of 2 <= numTables) x 16 */
 145   USHORT        entrySelectorZ; /* Log2(maximum power of 2 <= numTables). */
 146   USHORT        rangeShiftZ;    /* NumTables x 16-searchRange. */
 147   TableRecord   tables[VAR];    /* TableRecord entries. numTables items */
 148   public:
 149   DEFINE_SIZE_ARRAY (12, tables);
 150 } OpenTypeFontFace;
 151 
 152 
 153 /*
 154  * TrueType Collections
 155  */
 156 
 157 struct TTCHeaderVersion1
 158 {
 159   friend struct TTCHeader;
 160 
 161   inline unsigned int get_face_count (void) const { return table.len; }
 162   inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
 163 
 164   inline bool sanitize (hb_sanitize_context_t *c) const
 165   {
 166     TRACE_SANITIZE (this);
 167     return_trace (table.sanitize (c, this));
 168   }
 169 
 170   protected:
 171   Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
 172   FixedVersion  version;        /* Version of the TTC Header (1.0),
 173                                  * 0x00010000u */
 174   ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
 175                 table;          /* Array of offsets to the OffsetTable for each font
 176                                  * from the beginning of the file */
 177   public:
 178   DEFINE_SIZE_ARRAY (12, table);
 179 };
 180 
 181 struct TTCHeader
 182 {
 183   friend struct OpenTypeFontFile;
 184 
 185   private:
 186 
 187   inline unsigned int get_face_count (void) const
 188   {
 189     switch (u.header.version.major) {
 190     case 2: /* version 2 is compatible with version 1 */
 191     case 1: return u.version1.get_face_count ();
 192     default:return 0;
 193     }
 194   }
 195   inline const OpenTypeFontFace& get_face (unsigned int i) const
 196   {
 197     switch (u.header.version.major) {
 198     case 2: /* version 2 is compatible with version 1 */
 199     case 1: return u.version1.get_face (i);
 200     default:return Null(OpenTypeFontFace);
 201     }
 202   }
 203 
 204   inline bool sanitize (hb_sanitize_context_t *c) const
 205   {
 206     TRACE_SANITIZE (this);
 207     if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
 208     switch (u.header.version.major) {
 209     case 2: /* version 2 is compatible with version 1 */
 210     case 1: return_trace (u.version1.sanitize (c));
 211     default:return_trace (true);
 212     }
 213   }
 214 
 215   protected:
 216   union {
 217   struct {
 218   Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
 219   FixedVersion  version;        /* Version of the TTC Header (1.0 or 2.0),
 220                                  * 0x00010000u or 0x00020000u */
 221   }                     header;
 222   TTCHeaderVersion1     version1;
 223   } u;
 224 };
 225 
 226 
 227 /*
 228  * OpenType Font File
 229  */
 230 
 231 struct OpenTypeFontFile
 232 {
 233   static const hb_tag_t tableTag        = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
 234 
 235   static const hb_tag_t CFFTag          = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
 236   static const hb_tag_t TrueTypeTag     = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
 237   static const hb_tag_t TTCTag          = HB_TAG ('t','t','c','f'); /* TrueType Collection */
 238   static const hb_tag_t TrueTag         = HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */
 239   static const hb_tag_t Typ1Tag         = HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */
 240 
 241   inline hb_tag_t get_tag (void) const { return u.tag; }
 242 
 243   inline unsigned int get_face_count (void) const
 244   {
 245     switch (u.tag) {
 246     case CFFTag:        /* All the non-collection tags */
 247     case TrueTag:
 248     case Typ1Tag:
 249     case TrueTypeTag:   return 1;
 250     case TTCTag:        return u.ttcHeader.get_face_count ();
 251     default:            return 0;
 252     }
 253   }
 254   inline const OpenTypeFontFace& get_face (unsigned int i) const
 255   {
 256     switch (u.tag) {
 257     /* Note: for non-collection SFNT data we ignore index.  This is because
 258      * Apple dfont container is a container of SFNT's.  So each SFNT is a
 259      * non-TTC, but the index is more than zero. */
 260     case CFFTag:        /* All the non-collection tags */
 261     case TrueTag:
 262     case Typ1Tag:
 263     case TrueTypeTag:   return u.fontFace;
 264     case TTCTag:        return u.ttcHeader.get_face (i);
 265     default:            return Null(OpenTypeFontFace);
 266     }
 267   }
 268 
 269   inline bool sanitize (hb_sanitize_context_t *c) const
 270   {
 271     TRACE_SANITIZE (this);
 272     if (unlikely (!u.tag.sanitize (c))) return_trace (false);
 273     switch (u.tag) {
 274     case CFFTag:        /* All the non-collection tags */
 275     case TrueTag:
 276     case Typ1Tag:
 277     case TrueTypeTag:   return_trace (u.fontFace.sanitize (c));
 278     case TTCTag:        return_trace (u.ttcHeader.sanitize (c));
 279     default:            return_trace (true);
 280     }
 281   }
 282 
 283   protected:
 284   union {
 285   Tag                   tag;            /* 4-byte identifier. */
 286   OpenTypeFontFace      fontFace;
 287   TTCHeader             ttcHeader;
 288   } u;
 289   public:
 290   DEFINE_SIZE_UNION (4, tag);
 291 };
 292 
 293 
 294 } /* namespace OT */
 295 
 296 
 297 #endif /* HB_OPEN_FILE_PRIVATE_HH */