Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2016  Google, Inc.
      3  *
      4  *  This is part of HarfBuzz, a text shaping library.
      5  *
      6  * Permission is hereby granted, without written agreement and without
      7  * license or royalty fees, to use, copy, modify, and distribute this
      8  * software and its documentation for any purpose, provided that the
      9  * above copyright notice and the following two paragraphs appear in
     10  * all copies of this software.
     11  *
     12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16  * DAMAGE.
     17  *
     18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23  *
     24  * Google Author(s): Behdad Esfahbod
     25  */
     26 
     27 #ifndef HB_OT_POST_TABLE_HH
     28 #define HB_OT_POST_TABLE_HH
     29 
     30 #include "hb-open-type-private.hh"
     31 #include "hb-dsalgs.hh"
     32 
     33 #define HB_STRING_ARRAY_NAME format1_names
     34 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
     35 #include "hb-string-array.hh"
     36 #undef HB_STRING_ARRAY_LIST
     37 #undef HB_STRING_ARRAY_NAME
     38 
     39 #define NUM_FORMAT1_NAMES 258
     40 
     41 namespace OT {
     42 
     43 
     44 /*
     45  * post -- PostScript
     46  */
     47 
     48 #define HB_OT_TAG_post HB_TAG('p','o','s','t')
     49 
     50 
     51 struct postV2Tail
     52 {
     53   inline bool sanitize (hb_sanitize_context_t *c) const
     54   {
     55     TRACE_SANITIZE (this);
     56     return_trace (glyphNameIndex.sanitize (c));
     57   }
     58 
     59   ArrayOf<UINT16>glyphNameIndex;	/* This is not an offset, but is the
     60 					 * ordinal number of the glyph in 'post'
     61 					 * string tables. */
     62   UINT8		namesX[VAR];		/* Glyph names with length bytes [variable]
     63 					 * (a Pascal string). */
     64 
     65   DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
     66 };
     67 
     68 struct post
     69 {
     70   static const hb_tag_t tableTag = HB_OT_TAG_post;
     71 
     72   inline bool sanitize (hb_sanitize_context_t *c) const
     73   {
     74     TRACE_SANITIZE (this);
     75     if (unlikely (!c->check_struct (this)))
     76       return_trace (false);
     77     if (version.to_int () == 0x00020000)
     78     {
     79       const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
     80       return_trace (v2.sanitize (c));
     81     }
     82     return_trace (true);
     83   }
     84 
     85   struct accelerator_t
     86   {
     87     inline void init (hb_face_t *face)
     88     {
     89       blob = Sanitizer<post>::sanitize (face->reference_table (HB_OT_TAG_post));
     90       const post *table = Sanitizer<post>::lock_instance (blob);
     91       unsigned int table_length = hb_blob_get_length (blob);
     92 
     93       version = table->version.to_int ();
     94       index_to_offset.init ();
     95       if (version != 0x00020000)
     96         return;
     97 
     98       const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
     99 
    100       glyphNameIndex = &v2.glyphNameIndex;
    101       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
    102 
    103       const uint8_t *end = (uint8_t *) table + table_length;
    104       for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
    105       {
    106 	uint32_t *offset = index_to_offset.push ();
    107 	if (unlikely (!offset))
    108 	  break;
    109 	*offset = data - pool;
    110       }
    111     }
    112     inline void fini (void)
    113     {
    114       index_to_offset.finish ();
    115       free (gids_sorted_by_name);
    116     }
    117 
    118     inline bool get_glyph_name (hb_codepoint_t glyph,
    119 				char *buf, unsigned int buf_len) const
    120     {
    121       hb_string_t s = find_glyph_name (glyph);
    122       if (!s.len)
    123         return false;
    124       if (!buf_len)
    125 	return true;
    126       if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
    127         return false;
    128       strncpy (buf, s.bytes, s.len);
    129       buf[s.len] = '\0';
    130       return true;
    131     }
    132 
    133     inline bool get_glyph_from_name (const char *name, int len,
    134 				     hb_codepoint_t *glyph) const
    135     {
    136       unsigned int count = get_glyph_count ();
    137       if (unlikely (!count))
    138         return false;
    139 
    140       if (len < 0)
    141 	len = strlen (name);
    142 
    143       if (unlikely (!len))
    144 	return false;
    145 
    146     retry:
    147       uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
    148 
    149       if (unlikely (!gids))
    150       {
    151 	gids = (uint16_t *) malloc (count * sizeof (gids[0]));
    152 	if (unlikely (!gids))
    153 	  return false; /* Anything better?! */
    154 
    155 	for (unsigned int i = 0; i < count; i++)
    156 	  gids[i] = i;
    157 	hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
    158 
    159 	if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
    160 	  free (gids);
    161 	  goto retry;
    162 	}
    163       }
    164 
    165       hb_string_t st (name, len);
    166       const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
    167       if (gid)
    168       {
    169 	*glyph = *gid;
    170 	return true;
    171       }
    172 
    173       return false;
    174     }
    175 
    176     protected:
    177 
    178     inline unsigned int get_glyph_count (void) const
    179     {
    180       if (version == 0x00010000)
    181         return NUM_FORMAT1_NAMES;
    182 
    183       if (version == 0x00020000)
    184         return glyphNameIndex->len;
    185 
    186       return 0;
    187     }
    188 
    189     static inline int cmp_gids (const void *pa, const void *pb, void *arg)
    190     {
    191       const accelerator_t *thiz = (const accelerator_t *) arg;
    192       uint16_t a = * (const uint16_t *) pa;
    193       uint16_t b = * (const uint16_t *) pb;
    194       return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
    195     }
    196 
    197     static inline int cmp_key (const void *pk, const void *po, void *arg)
    198     {
    199       const accelerator_t *thiz = (const accelerator_t *) arg;
    200       const hb_string_t *key = (const hb_string_t *) pk;
    201       uint16_t o = * (const uint16_t *) po;
    202       return thiz->find_glyph_name (o).cmp (*key);
    203     }
    204 
    205     inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const
    206     {
    207       if (version == 0x00010000)
    208       {
    209 	if (glyph >= NUM_FORMAT1_NAMES)
    210 	  return hb_string_t ();
    211 
    212 	return format1_names (glyph);
    213       }
    214 
    215       if (version != 0x00020000 || glyph >= glyphNameIndex->len)
    216 	return hb_string_t ();
    217 
    218       unsigned int index = glyphNameIndex->array[glyph];
    219       if (index < NUM_FORMAT1_NAMES)
    220 	return format1_names (index);
    221       index -= NUM_FORMAT1_NAMES;
    222 
    223       if (index >= index_to_offset.len)
    224 	return hb_string_t ();
    225       unsigned int offset = index_to_offset.array[index];
    226 
    227       const uint8_t *data = pool + offset;
    228       unsigned int name_length = *data;
    229       data++;
    230 
    231       return hb_string_t ((const char *) data, name_length);
    232     }
    233 
    234     private:
    235     hb_blob_t *blob;
    236     uint32_t version;
    237     const ArrayOf<UINT16> *glyphNameIndex;
    238     hb_prealloced_array_t<uint32_t, 1> index_to_offset;
    239     const uint8_t *pool;
    240     mutable uint16_t *gids_sorted_by_name;
    241   };
    242 
    243   public:
    244   FixedVersion<>version;		/* 0x00010000 for version 1.0
    245 					 * 0x00020000 for version 2.0
    246 					 * 0x00025000 for version 2.5 (deprecated)
    247 					 * 0x00030000 for version 3.0 */
    248   Fixed		italicAngle;		/* Italic angle in counter-clockwise degrees
    249 					 * from the vertical. Zero for upright text,
    250 					 * negative for text that leans to the right
    251 					 * (forward). */
    252   FWORD		underlinePosition;	/* This is the suggested distance of the top
    253 					 * of the underline from the baseline
    254 					 * (negative values indicate below baseline).
    255 					 * The PostScript definition of this FontInfo
    256 					 * dictionary key (the y coordinate of the
    257 					 * center of the stroke) is not used for
    258 					 * historical reasons. The value of the
    259 					 * PostScript key may be calculated by
    260 					 * subtracting half the underlineThickness
    261 					 * from the value of this field. */
    262   FWORD		underlineThickness;	/* Suggested values for the underline
    263 					   thickness. */
    264   UINT32		isFixedPitch;		/* Set to 0 if the font is proportionally
    265 					 * spaced, non-zero if the font is not
    266 					 * proportionally spaced (i.e. monospaced). */
    267   UINT32		minMemType42;		/* Minimum memory usage when an OpenType font
    268 					 * is downloaded. */
    269   UINT32		maxMemType42;		/* Maximum memory usage when an OpenType font
    270 					 * is downloaded. */
    271   UINT32		minMemType1;		/* Minimum memory usage when an OpenType font
    272 					 * is downloaded as a Type 1 font. */
    273   UINT32		maxMemType1;		/* Maximum memory usage when an OpenType font
    274 					 * is downloaded as a Type 1 font. */
    275 /*postV2Tail	v2[VAR];*/
    276   DEFINE_SIZE_STATIC (32);
    277 };
    278 
    279 } /* namespace OT */
    280 
    281 
    282 #endif /* HB_OT_POST_TABLE_HH */
    283