hb-ot-cff-common.hh 21.6 KB
Newer Older
M
Michiharu Ariza 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright © 2018 Adobe Systems Incorporated.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Adobe Author(s): Michiharu Ariza
 */
M
Michiharu Ariza 已提交
26 27
#ifndef HB_OT_CFF_COMMON_HH
#define HB_OT_CFF_COMMON_HH
M
Michiharu Ariza 已提交
28

29 30 31
#include "hb-open-type.hh"
#include "hb-ot-layout-common.hh"
#include "hb-cff-interp-dict-common.hh"
M
Michiharu Ariza 已提交
32
#include "hb-subset-plan.hh"
M
Michiharu Ariza 已提交
33 34 35 36 37

namespace CFF {

using namespace OT;

M
Michiharu Ariza 已提交
38 39
#define CFF_UNDEF_CODE  0xFFFFFFFF

M
Michiharu Ariza 已提交
40 41 42 43 44
/* utility macro */
template<typename Type>
static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
{ return offset? (* reinterpret_cast<const Type*> ((const char *) P + offset)): Null(Type); }

M
Michiharu Ariza 已提交
45 46 47 48 49 50 51 52 53 54 55
inline unsigned int calcOffSize(unsigned int offset)
{
  unsigned int size = 1;
  while ((offset & ~0xFF) != 0)
  {
    size++;
    offset >>= 8;
  }
  assert (size <= 4);
  return size;
}
M
Michiharu Ariza 已提交
56 57

/* CFF INDEX */
M
Michiharu Ariza 已提交
58
template <typename COUNT>
59
struct CFFIndex
M
Michiharu Ariza 已提交
60 61 62 63
{
  inline bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
64 65 66 67
    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
                          (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
                           c->check_array (offsets, offSize, count + 1) &&
                           c->check_array (data_base (), 1, max_offset () - 1))));
M
Michiharu Ariza 已提交
68 69
  }

M
Michiharu Ariza 已提交
70
  inline static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
M
Michiharu Ariza 已提交
71 72
  { return offSize * (count + 1); }

M
Michiharu Ariza 已提交
73 74 75 76 77 78
  inline unsigned int offset_array_size (void) const
  { return calculate_offset_array_size (offSize, count); }

  inline static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
  { return min_size + calculate_offset_array_size (offSize, count) + dataSize; }

79
  inline bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
M
Michiharu Ariza 已提交
80
  {
M
Michiharu Ariza 已提交
81
    TRACE_SERIALIZE (this);
M
Michiharu Ariza 已提交
82
    unsigned int size = src.get_size ();
83
    CFFIndex *dest = c->allocate_size<CFFIndex> (size);
M
Michiharu Ariza 已提交
84 85 86 87 88 89
    if (unlikely (dest == nullptr)) return_trace (false);
    memcpy (dest, &src, size);
    return_trace (true);
  }

  inline bool serialize (hb_serialize_context_t *c,
M
Michiharu Ariza 已提交
90 91
                         unsigned int offSize_,
                         const hb_vector_t<ByteStr> &byteArray)
M
Michiharu Ariza 已提交
92 93
  {
    TRACE_SERIALIZE (this);
94
    /* serialize CFFIndex header */
M
Michiharu Ariza 已提交
95
    if (unlikely (!c->extend_min (*this))) return_trace (false);
M
Michiharu Ariza 已提交
96 97 98
    this->count.set (byteArray.len);
    this->offSize.set (offSize_);
    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.len + 1))))
M
Michiharu Ariza 已提交
99 100 101 102
      return_trace (false);
  
    /* serialize indices */
    unsigned int  offset = 1;
M
Michiharu Ariza 已提交
103
    unsigned int  i = 0;
M
Michiharu Ariza 已提交
104
    for (; i < byteArray.len; i++)
M
Michiharu Ariza 已提交
105 106
    {
      set_offset_at (i, offset);
M
Michiharu Ariza 已提交
107
      offset += byteArray[i].get_size ();
M
Michiharu Ariza 已提交
108
    }
M
Michiharu Ariza 已提交
109
    set_offset_at (i, offset);
M
Michiharu Ariza 已提交
110 111

    /* serialize data */
M
Michiharu Ariza 已提交
112
    for (unsigned int i = 0; i < byteArray.len; i++)
M
Michiharu Ariza 已提交
113
    {
M
Michiharu Ariza 已提交
114 115 116
      ByteStr  *dest = c->start_embed<ByteStr> ();
      if (unlikely (dest == nullptr ||
                    !dest->serialize (c, byteArray[i])))
M
Michiharu Ariza 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
        return_trace (false);
    }
    return_trace (true);
  }

  inline void set_offset_at (unsigned int index, unsigned int offset)
  {
    HBUINT8 *p = offsets + offSize * index + offSize;
    unsigned int size = offSize;
    for (; size; size--)
    {
      --p;
      p->set (offset & 0xFF);
      offset >>= 8;
    }
  }

M
Michiharu Ariza 已提交
134 135
  inline const unsigned int offset_at (unsigned int index) const
  {
136
    assert (index <= count);
M
Michiharu Ariza 已提交
137 138 139 140 141 142 143 144 145 146 147 148
    const HBUINT8 *p = offsets + offSize * index;
    unsigned int size = offSize;
    unsigned int offset = 0;
    for (; size; size--)
      offset = (offset << 8) + *p++;
    return offset;
  }

  inline const unsigned int length_at (unsigned int index) const
  { return offset_at (index + 1) - offset_at (index); }

  inline const char *data_base (void) const
M
Michiharu Ariza 已提交
149
  { return (const char *)this + min_size + offset_array_size (); }
M
Michiharu Ariza 已提交
150 151 152 153

  inline unsigned int data_size (void) const
  { return HBINT8::static_size; };

M
Michiharu Ariza 已提交
154
  ByteStr operator [] (unsigned int index) const
M
Michiharu Ariza 已提交
155 156
  {
    if (likely (index < count))
M
Michiharu Ariza 已提交
157 158 159
      return ByteStr (data_base () + offset_at (index) - 1, offset_at (index + 1) - offset_at (index));
    else
      return Null(ByteStr);
M
Michiharu Ariza 已提交
160 161 162
  }

  inline unsigned int get_size (void) const
M
Michiharu Ariza 已提交
163
  {
164
    if (this != &Null(CFFIndex))
165 166 167 168
    {
      if (count > 0)
        return min_size + offset_array_size () + (offset_at (count) - 1);
      else
169
        return count.static_size;  /* empty CFFIndex contains count only */
170
    }
M
Michiharu Ariza 已提交
171 172 173
    else
      return 0;
  }
M
Michiharu Ariza 已提交
174

175 176 177 178 179 180 181 182 183 184 185 186 187
  protected:
  inline unsigned int max_offset (void) const
  {
    unsigned int max = 0;
    for (unsigned int i = 0; i <= count; i++)
    {
      unsigned int off = offset_at (i);
      if (off > max) max = off;
    }
    return max;
  }

  public:
M
Michiharu Ariza 已提交
188
  COUNT     count;        /* Number of object data. Note there are (count+1) offsets */
M
Michiharu Ariza 已提交
189 190 191 192
  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
  /* HBUINT8 data[VAR];      Object data */
  public:
M
Michiharu Ariza 已提交
193
  DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
M
Michiharu Ariza 已提交
194 195
};

M
Michiharu Ariza 已提交
196
template <typename COUNT, typename TYPE>
M
Michiharu Ariza 已提交
197
struct CFFIndexOf : CFFIndex<COUNT>
M
Michiharu Ariza 已提交
198
{
M
Michiharu Ariza 已提交
199
  inline const ByteStr operator [] (unsigned int index) const
M
Michiharu Ariza 已提交
200
  {
201 202
    if (likely (index < CFFIndex<COUNT>::count))
      return ByteStr (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
M
Michiharu Ariza 已提交
203
    return Null(ByteStr);
M
Michiharu Ariza 已提交
204
  }
M
Michiharu Ariza 已提交
205 206 207 208

  template <typename DATA, typename PARAM1, typename PARAM2>
  inline bool serialize (hb_serialize_context_t *c,
                         unsigned int offSize_,
M
Michiharu Ariza 已提交
209 210
                         const DATA *dataArray,
                         unsigned int dataArrayLen,
M
Michiharu Ariza 已提交
211 212 213 214 215
                         const hb_vector_t<unsigned int> &dataSizeArray,
                         const PARAM1 &param1,
                         const PARAM2 &param2)
  {
    TRACE_SERIALIZE (this);
216
    /* serialize CFFIndex header */
M
Michiharu Ariza 已提交
217
    if (unlikely (!c->extend_min (*this))) return_trace (false);
M
Michiharu Ariza 已提交
218
    this->count.set (dataArrayLen);
M
Michiharu Ariza 已提交
219
    this->offSize.set (offSize_);
M
Michiharu Ariza 已提交
220
    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
M
Michiharu Ariza 已提交
221 222 223 224 225
      return_trace (false);
  
    /* serialize indices */
    unsigned int  offset = 1;
    unsigned int  i = 0;
M
Michiharu Ariza 已提交
226
    for (; i < dataArrayLen; i++)
M
Michiharu Ariza 已提交
227
    {
228
      CFFIndex<COUNT>::set_offset_at (i, offset);
M
Michiharu Ariza 已提交
229 230
      offset += dataSizeArray[i];
    }
231
    CFFIndex<COUNT>::set_offset_at (i, offset);
M
Michiharu Ariza 已提交
232 233

    /* serialize data */
M
Michiharu Ariza 已提交
234
    for (unsigned int i = 0; i < dataArrayLen; i++)
M
Michiharu Ariza 已提交
235 236 237 238 239 240 241 242 243 244 245 246
    {
      TYPE  *dest = c->start_embed<TYPE> ();
      if (unlikely (dest == nullptr ||
                    !dest->serialize (c, dataArray[i], param1, param2)))
        return_trace (false);
    }
    return_trace (true);
  }

  /* in parallel to above */
  template <typename DATA, typename PARAM>
  inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
M
Michiharu Ariza 已提交
247 248
                                                        const DATA *dataArray,
                                                        unsigned int dataArrayLen,
M
Michiharu Ariza 已提交
249 250 251 252 253
                                                        hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
                                                        const PARAM &param)
  {
    /* determine offset size */
    unsigned int  totalDataSize = 0;
M
Michiharu Ariza 已提交
254
    for (unsigned int i = 0; i < dataArrayLen; i++)
M
Michiharu Ariza 已提交
255 256 257 258 259 260 261
    {
      unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
      dataSizeArray[i] = dataSize;
      totalDataSize += dataSize;
    }
    offSize_ = calcOffSize (totalDataSize);

M
Michiharu Ariza 已提交
262
    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
M
Michiharu Ariza 已提交
263 264 265
  }
};

M
Michiharu Ariza 已提交
266
/* Top Dict, Font Dict, Private Dict */
M
Michiharu Ariza 已提交
267 268
struct Dict : UnsizedByteStr
{
269
  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
M
Michiharu Ariza 已提交
270
  inline bool serialize (hb_serialize_context_t *c,
271
                        const DICTVAL &dictval,
M
Michiharu Ariza 已提交
272 273 274 275
                        OP_SERIALIZER& opszr,
                        PARAM& param)
  {
    TRACE_SERIALIZE (this);
M
Michiharu Ariza 已提交
276
    for (unsigned int i = 0; i < dictval.getNumValues (); i++)
M
Michiharu Ariza 已提交
277
    {
M
Michiharu Ariza 已提交
278
      if (unlikely (!opszr.serialize (c, dictval[i], param)))
M
Michiharu Ariza 已提交
279 280 281 282
        return_trace (false);
    }
    return_trace (true);
  }
M
Michiharu Ariza 已提交
283

M
Michiharu Ariza 已提交
284
  /* in parallel to above */
285 286
  template <typename DICTVAL, typename OP_SERIALIZER>
  inline static unsigned int calculate_serialized_size (const DICTVAL &dictval,
M
Michiharu Ariza 已提交
287 288 289
                                                        OP_SERIALIZER& opszr)
  {
    unsigned int size = 0;
M
Michiharu Ariza 已提交
290 291
    for (unsigned int i = 0; i < dictval.getNumValues (); i++)
      size += opszr.calculate_serialized_size (dictval[i]);
M
Michiharu Ariza 已提交
292 293 294 295
    return size;
  }

  template <typename INTTYPE, int minVal, int maxVal>
M
Michiharu Ariza 已提交
296
  inline static bool serialize_int_op (hb_serialize_context_t *c, OpCode op, int value, OpCode intOp)
M
Michiharu Ariza 已提交
297 298 299 300 301 302 303
  {
    // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
    if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
      return false;

    TRACE_SERIALIZE (this);
    /* serialize the opcode */
M
Michiharu Ariza 已提交
304
    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
M
Michiharu Ariza 已提交
305
    if (unlikely (p == nullptr)) return_trace (false);
M
Michiharu Ariza 已提交
306
    if (Is_OpCode_ESC (op))
M
Michiharu Ariza 已提交
307 308
    {
      p->set (OpCode_escape);
M
Michiharu Ariza 已提交
309
      op = Unmake_OpCode_ESC (op);
M
Michiharu Ariza 已提交
310 311 312 313 314 315
      p++;
    }
    p->set (op);
    return_trace (true);
  }

M
Michiharu Ariza 已提交
316 317 318 319 320 321
  inline static bool serialize_uint4_op (hb_serialize_context_t *c, OpCode op, int value)
  { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }

  inline static bool serialize_uint2_op (hb_serialize_context_t *c, OpCode op, int value)
  { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }

M
Michiharu Ariza 已提交
322
  inline static bool serialize_offset4_op (hb_serialize_context_t *c, OpCode op, int value)
M
Michiharu Ariza 已提交
323 324 325 326
  {
    if (value == 0) return true;
    return serialize_uint4_op (c, op, value);
  }
M
Michiharu Ariza 已提交
327 328

  inline static bool serialize_offset2_op (hb_serialize_context_t *c, OpCode op, int value)
M
Michiharu Ariza 已提交
329 330 331 332
  {
    if (value == 0) return true;
    return serialize_uint2_op (c, op, value);
  }
M
Michiharu Ariza 已提交
333 334 335 336 337 338
};

struct TopDict : Dict {};
struct FontDict : Dict {};
struct PrivateDict : Dict {};

M
Michiharu Ariza 已提交
339 340
struct TableInfo
{
M
Michiharu Ariza 已提交
341
  void init (void) { offSize = offset = size = 0; }
M
Michiharu Ariza 已提交
342 343 344

  unsigned int    offset;
  unsigned int    size;
M
Michiharu Ariza 已提交
345
  unsigned int    offSize;
M
Michiharu Ariza 已提交
346 347
};

M
Michiharu Ariza 已提交
348 349 350
/* used to remap font index or SID from fullset to subset.
 * set to CFF_UNDEF_CODE if excluded from subset */
struct Remap : hb_vector_t<hb_codepoint_t>
351 352 353 354 355 356 357
{
  inline void init (void)
  { hb_vector_t<hb_codepoint_t>::init (); }

  inline void fini (void)
  { hb_vector_t<hb_codepoint_t>::fini (); }

M
Michiharu Ariza 已提交
358 359 360 361 362 363 364 365 366 367
  inline bool reset (unsigned int count)
  {
    if (unlikely (!hb_vector_t<hb_codepoint_t>::resize (count)))
      return false;
    for (unsigned int i = 0; i < len; i++)
      (*this)[i] = CFF_UNDEF_CODE;
    count = 0;
    return true;
  }

368 369 370
  inline bool fullset (void) const
  {
    for (unsigned int i = 0; i < len; i++)
M
Michiharu Ariza 已提交
371
      if (hb_vector_t<hb_codepoint_t>::operator[] (i) == CFF_UNDEF_CODE)
372 373 374 375
        return false;
    return true;
  }

M
Michiharu Ariza 已提交
376 377
  inline bool excludes (hb_codepoint_t id) const
  { return (id < len) && ((*this)[id] == CFF_UNDEF_CODE); }
378 379 380 381 382 383 384 385 386 387 388 389 390 391

  inline hb_codepoint_t operator[] (hb_codepoint_t i) const
  {
    if (fullset ())
      return i;
    else
      return hb_vector_t<hb_codepoint_t>::operator[] (i);
  }

  inline hb_codepoint_t &operator[] (hb_codepoint_t i)
  {
    assert (i < len);
    return hb_vector_t<hb_codepoint_t>::operator[] (i);
  }
M
Michiharu Ariza 已提交
392 393 394 395 396 397 398 399 400 401 402 403 404

  inline unsigned int add (unsigned int i)
  {
    if ((*this)[i] == CFF_UNDEF_CODE)
      (*this)[i] = count++;
    return (*this)[i];
  }

  inline hb_codepoint_t get_count (void) const
  { return count; }

  protected:
  hb_codepoint_t  count;
405 406
};

M
Michiharu Ariza 已提交
407
template <typename COUNT>
M
Michiharu Ariza 已提交
408
struct FDArray : CFFIndexOf<COUNT, FontDict>
M
Michiharu Ariza 已提交
409
{
M
Michiharu Ariza 已提交
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
  /* used by CFF1 */
  template <typename DICTVAL, typename OP_SERIALIZER>
  inline bool serialize (hb_serialize_context_t *c,
                        unsigned int offSize_,
                        const hb_vector_t<DICTVAL> &fontDicts,
                        OP_SERIALIZER& opszr)
  {
    TRACE_SERIALIZE (this);
    if (unlikely (!c->extend_min (*this))) return_trace (false);
    this->count.set (fontDicts.len);
    this->offSize.set (offSize_);
    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.len + 1))))
      return_trace (false);
    
    /* serialize font dict offsets */
    unsigned int  offset = 1;
    unsigned int fid = 0;
    for (; fid < fontDicts.len; fid++)
    {
      CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
      offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
    }
    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);

    /* serialize font dicts */
    for (unsigned int i = 0; i < fontDicts.len; i++)
    {
      FontDict *dict = c->start_embed<FontDict> ();
      if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
        return_trace (false);
    }
    return_trace (true);
  }
  
  /* used by CFF2 */
M
Michiharu Ariza 已提交
445 446
  template <typename DICTVAL, typename OP_SERIALIZER>
  inline bool serialize (hb_serialize_context_t *c,
M
Michiharu Ariza 已提交
447
                        unsigned int offSize_,
M
Michiharu Ariza 已提交
448
                        const hb_vector_t<DICTVAL> &fontDicts,
M
Michiharu Ariza 已提交
449
                        unsigned int fdCount,
M
Michiharu Ariza 已提交
450
                        const Remap &fdmap,
M
Michiharu Ariza 已提交
451
                        OP_SERIALIZER& opszr,
M
Michiharu Ariza 已提交
452
                        const hb_vector_t<TableInfo> &privateInfos)
M
Michiharu Ariza 已提交
453 454 455
  {
    TRACE_SERIALIZE (this);
    if (unlikely (!c->extend_min (*this))) return_trace (false);
M
Michiharu Ariza 已提交
456
    this->count.set (fdCount);
M
Michiharu Ariza 已提交
457 458
    this->offSize.set (offSize_);
    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
M
Michiharu Ariza 已提交
459 460 461 462
      return_trace (false);
    
    /* serialize font dict offsets */
    unsigned int  offset = 1;
M
Michiharu Ariza 已提交
463 464
    unsigned int  fid = 0;
    for (unsigned i = 0; i < fontDicts.len; i++)
465
      if (!fdmap.excludes (i))
M
Michiharu Ariza 已提交
466
      {
M
Michiharu Ariza 已提交
467
        CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
M
Michiharu Ariza 已提交
468 469
        offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
      }
M
Michiharu Ariza 已提交
470
    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
M
Michiharu Ariza 已提交
471 472 473

    /* serialize font dicts */
    for (unsigned int i = 0; i < fontDicts.len; i++)
474
      if (!fdmap.excludes (i))
M
Michiharu Ariza 已提交
475 476
      {
        FontDict *dict = c->start_embed<FontDict> ();
477
        if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
M
Michiharu Ariza 已提交
478 479
          return_trace (false);
      }
M
Michiharu Ariza 已提交
480 481 482 483 484
    return_trace (true);
  }
  
  /* in parallel to above */
  template <typename OP_SERIALIZER, typename DICTVAL>
M
Michiharu Ariza 已提交
485
  inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
M
Michiharu Ariza 已提交
486
                                                        const hb_vector_t<DICTVAL> &fontDicts,
M
Michiharu Ariza 已提交
487
                                                        unsigned int fdCount,
M
Michiharu Ariza 已提交
488
                                                        const Remap &fdmap,
M
Michiharu Ariza 已提交
489 490 491 492
                                                        OP_SERIALIZER& opszr)
  {
    unsigned int dictsSize = 0;
    for (unsigned int i = 0; i < fontDicts.len; i++)
493
      if (!fdmap.excludes (i))
M
Michiharu Ariza 已提交
494
        dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
M
Michiharu Ariza 已提交
495

M
Michiharu Ariza 已提交
496
    offSize_ = calcOffSize (dictsSize + 1);
497
    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
M
Michiharu Ariza 已提交
498 499
  }
};
M
Michiharu Ariza 已提交
500 501 502

/* FDSelect */
struct FDSelect0 {
M
Michiharu Ariza 已提交
503
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
504 505
  {
    TRACE_SANITIZE (this);
M
Michiharu Ariza 已提交
506 507 508 509 510 511 512 513 514 515 516 517
    if (unlikely (!(c->check_struct (this))))
      return_trace (false);
    for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
      if (unlikely (!fds[i].sanitize (c)))
        return_trace (false);

    return_trace (true);
  }

  inline hb_codepoint_t get_fd (hb_codepoint_t glyph) const
  {
    return (hb_codepoint_t)fds[glyph];
518 519
  }

M
Michiharu Ariza 已提交
520 521 522
  inline unsigned int get_size (unsigned int num_glyphs) const
  { return HBUINT8::static_size * num_glyphs; }

M
Michiharu Ariza 已提交
523
  HBUINT8     fds[VAR];
524 525

  DEFINE_SIZE_MIN (1);
M
Michiharu Ariza 已提交
526 527
};

M
Michiharu Ariza 已提交
528 529 530
template <typename GID_TYPE, typename FD_TYPE>
struct FDSelect3_4_Range {
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
531 532
  {
    TRACE_SANITIZE (this);
M
Michiharu Ariza 已提交
533
    return_trace (likely (c->check_struct (this) && (first < c->get_num_glyphs ()) && (fd < fdcount)));
534 535
  }

M
Michiharu Ariza 已提交
536 537
  GID_TYPE    first;
  FD_TYPE     fd;
538

M
Michiharu Ariza 已提交
539
  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
M
Michiharu Ariza 已提交
540 541
};

M
Michiharu Ariza 已提交
542 543
template <typename GID_TYPE, typename FD_TYPE>
struct FDSelect3_4 {
M
Michiharu Ariza 已提交
544
  inline unsigned int get_size (void) const
M
Michiharu Ariza 已提交
545
  { return GID_TYPE::static_size * 2 + FDSelect3_4_Range<GID_TYPE, FD_TYPE>::static_size * nRanges; }
M
Michiharu Ariza 已提交
546

M
Michiharu Ariza 已提交
547
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
548 549
  {
    TRACE_SANITIZE (this);
M
Michiharu Ariza 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563
    if (unlikely (!(c->check_struct (this) && (nRanges > 0) && (ranges[0].first == 0))))
      return_trace (false);

    for (unsigned int i = 0; i < nRanges; i++)
    {
      if (unlikely (!ranges[i].sanitize (c, fdcount)))
        return_trace (false);
      if ((0 < i) && unlikely (ranges[i - 1].first >= ranges[i].first))
        return_trace (false);
    }
    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
      return_trace (false);

    return_trace (true);
564 565
  }

M
Michiharu Ariza 已提交
566 567
  inline hb_codepoint_t get_fd (hb_codepoint_t glyph) const
  {
M
Michiharu Ariza 已提交
568 569 570
    for (unsigned int i = 1; i < nRanges; i++)
      if (glyph < ranges[i].first)
        return (hb_codepoint_t)ranges[i - 1].fd;
M
Michiharu Ariza 已提交
571 572 573

    assert (false);
  }
574

M
Michiharu Ariza 已提交
575 576 577 578 579 580 581 582
  inline GID_TYPE &sentinel (void)  { return StructAfter<GID_TYPE> (ranges[nRanges - 1]); }
  inline const GID_TYPE &sentinel (void) const  { return StructAfter<GID_TYPE> (ranges[nRanges - 1]); }

  GID_TYPE         nRanges;
  FDSelect3_4_Range<GID_TYPE, FD_TYPE>  ranges[VAR];
  /* GID_TYPE sentinel */

  DEFINE_SIZE_ARRAY (GID_TYPE::static_size * 2, ranges);
M
Michiharu Ariza 已提交
583 584
};

M
Michiharu Ariza 已提交
585 586 587
typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;

M
Michiharu Ariza 已提交
588
struct FDSelect {
M
Michiharu Ariza 已提交
589
  inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
590 591
  {
    TRACE_SANITIZE (this);
M
Michiharu Ariza 已提交
592

593
    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
M
Michiharu Ariza 已提交
594 595 596
                          (format == 0)?
                          u.format0.sanitize (c, fdcount):
                          u.format3.sanitize (c, fdcount)));
597 598
  }

M
Michiharu Ariza 已提交
599 600
  inline bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
  {
M
Michiharu Ariza 已提交
601
    TRACE_SERIALIZE (this);
M
Michiharu Ariza 已提交
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
    unsigned int size = src.get_size (num_glyphs);
    FDSelect *dest = c->allocate_size<FDSelect> (size);
    if (unlikely (dest == nullptr)) return_trace (false);
    memcpy (dest, &src, size);
    return_trace (true);
  }

  inline unsigned int calculate_serialized_size (unsigned int num_glyphs) const
  { return get_size (num_glyphs); }

  inline unsigned int get_size (unsigned int num_glyphs) const
  {
    unsigned int size = format.static_size;
    if (format == 0)
      size += u.format0.get_size (num_glyphs);
M
Michiharu Ariza 已提交
617
    else
M
Michiharu Ariza 已提交
618 619 620 621
      size += u.format3.get_size ();
    return size;
  }

M
Michiharu Ariza 已提交
622 623
  inline hb_codepoint_t get_fd (hb_codepoint_t glyph) const
  {
M
Michiharu Ariza 已提交
624 625
    if (this == &Null(FDSelect))
      return 0;
M
Michiharu Ariza 已提交
626 627 628 629 630 631
    if (format == 0)
      return u.format0.get_fd (glyph);
    else
      return u.format3.get_fd (glyph);
  }

M
Michiharu Ariza 已提交
632 633 634 635 636
  HBUINT8       format;
  union {
    FDSelect0   format0;
    FDSelect3   format3;
  } u;
637

M
Michiharu Ariza 已提交
638
  DEFINE_SIZE_MIN (1);
M
Michiharu Ariza 已提交
639 640
};

M
Michiharu Ariza 已提交
641
template <typename COUNT>
642
struct Subrs : CFFIndex<COUNT>
M
Michiharu Ariza 已提交
643
{
M
Michiharu Ariza 已提交
644
  inline bool serialize (hb_serialize_context_t *c, const Subrs<COUNT> &subrs, unsigned int offSize, const hb_set_t *set, const ByteStr& nullStr = ByteStr())
M
Michiharu Ariza 已提交
645
  {
M
Michiharu Ariza 已提交
646
    TRACE_SERIALIZE (this);
M
Michiharu Ariza 已提交
647 648
    if (&subrs == &Null(Subrs<COUNT>))
      return_trace (true);
M
Michiharu Ariza 已提交
649
    if ((subrs.count == 0) || (set == nullptr) || (hb_set_is_empty (set)))
M
Michiharu Ariza 已提交
650
    {
M
Michiharu Ariza 已提交
651 652
      if (!unlikely (c->allocate_size<COUNT> (COUNT::static_size)))
        return_trace (false);
653
      CFFIndex<COUNT>::count.set (0);
M
Michiharu Ariza 已提交
654
      return_trace (true);
M
Michiharu Ariza 已提交
655 656
    }
    
M
Michiharu Ariza 已提交
657 658 659 660 661 662
    hb_vector_t<ByteStr> bytesArray;
    bytesArray.init ();
    if (!bytesArray.resize (subrs.count))
      return_trace (false);
    for (hb_codepoint_t i = 0; i < subrs.count; i++)
      bytesArray[i] = (hb_set_has (set, i))? subrs[i]: nullStr;
M
Michiharu Ariza 已提交
663

664
    bool result = CFFIndex<COUNT>::serialize (c, offSize, bytesArray);
M
Michiharu Ariza 已提交
665 666
    bytesArray.fini ();
    return_trace (result);
M
Michiharu Ariza 已提交
667 668
  }
  
M
Michiharu Ariza 已提交
669 670
  /* in parallel to above */
  inline unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const hb_set_t *set, unsigned int nullStrSize = 0) const
M
Michiharu Ariza 已提交
671
  {
M
Michiharu Ariza 已提交
672 673
    if (this == &Null(Subrs<COUNT>))
      return 0;
674
    unsigned int  count_ = CFFIndex<COUNT>::count;
M
Michiharu Ariza 已提交
675 676 677
    offSize = 0;
    if ((count_ == 0) || (hb_set_get_population (set) == 0))
      return COUNT::static_size;
M
Michiharu Ariza 已提交
678

M
Michiharu Ariza 已提交
679 680
    unsigned int dataSize = 0;
    for (hb_codepoint_t i = 0; i < count_; i++)
M
Michiharu Ariza 已提交
681
    {
M
Michiharu Ariza 已提交
682 683 684 685
      if (hb_set_has (set, i))
        dataSize += (*this)[i].len;
      else
        dataSize += nullStrSize;
M
Michiharu Ariza 已提交
686
    }
M
Michiharu Ariza 已提交
687
    offSize = calcOffSize(dataSize);
688
    return CFFIndex<COUNT>::calculate_serialized_size (offSize, count_, dataSize);
M
Michiharu Ariza 已提交
689 690 691 692 693
  }
};

} /* namespace CFF */

M
Michiharu Ariza 已提交
694
#endif /* HB_OT_CFF_COMMON_HH */
M
Michiharu Ariza 已提交
695