subset CFF1 Encoding & Charset
fixed misc Charset bugs added source file hb-ot-cff1.table.cc renamed things for clarity & consistency
This commit is contained in:
parent
5ea03d2951
commit
aca73c9df2
|
@ -27,6 +27,7 @@ HB_BASE_sources = \
|
||||||
hb-ot-cmap-table.hh \
|
hb-ot-cmap-table.hh \
|
||||||
hb-ot-glyf-table.hh \
|
hb-ot-glyf-table.hh \
|
||||||
hb-ot-cff1-table.hh \
|
hb-ot-cff1-table.hh \
|
||||||
|
hb-ot-cff1-table.cc \
|
||||||
hb-ot-cff2-table.hh \
|
hb-ot-cff2-table.hh \
|
||||||
hb-ot-hdmx-table.hh \
|
hb-ot-hdmx-table.hh \
|
||||||
hb-ot-head-table.hh \
|
hb-ot-head-table.hh \
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct DictValues
|
||||||
values.fini ();
|
values.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void pushVal (OpCode op, const SubByteStr& substr)
|
inline void addOp (OpCode op, const SubByteStr& substr = SubByteStr ())
|
||||||
{
|
{
|
||||||
VAL *val = values.push ();
|
VAL *val = values.push ();
|
||||||
val->op = op;
|
val->op = op;
|
||||||
|
@ -74,7 +74,7 @@ struct DictValues
|
||||||
opStart = substr.offset;
|
opStart = substr.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void pushVal (OpCode op, const SubByteStr& substr, const VAL &v)
|
inline void addOp (OpCode op, const SubByteStr& substr, const VAL &v)
|
||||||
{
|
{
|
||||||
VAL *val = values.push (v);
|
VAL *val = values.push (v);
|
||||||
val->op = op;
|
val->op = op;
|
||||||
|
@ -82,6 +82,17 @@ struct DictValues
|
||||||
opStart = substr.offset;
|
opStart = substr.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool hasOp (OpCode op) const
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < getNumValues (); i++)
|
||||||
|
if (getValue (i).op == op) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned getNumValues (void) const { return values.len; }
|
||||||
|
inline const VAL &getValue (unsigned int i) const { return values[i]; }
|
||||||
|
inline const VAL &operator [] (unsigned int i) const { return getValue (i); }
|
||||||
|
|
||||||
unsigned int opStart;
|
unsigned int opStart;
|
||||||
hb_vector_t<VAL> values;
|
hb_vector_t<VAL> values;
|
||||||
};
|
};
|
||||||
|
|
|
@ -192,7 +192,7 @@ struct CFFIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename COUNT, typename TYPE>
|
template <typename COUNT, typename TYPE>
|
||||||
struct IndexOf : CFFIndex<COUNT>
|
struct CFFIndexOf : CFFIndex<COUNT>
|
||||||
{
|
{
|
||||||
inline const ByteStr operator [] (unsigned int index) const
|
inline const ByteStr operator [] (unsigned int index) const
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,8 @@ struct IndexOf : CFFIndex<COUNT>
|
||||||
template <typename DATA, typename PARAM1, typename PARAM2>
|
template <typename DATA, typename PARAM1, typename PARAM2>
|
||||||
inline bool serialize (hb_serialize_context_t *c,
|
inline bool serialize (hb_serialize_context_t *c,
|
||||||
unsigned int offSize_,
|
unsigned int offSize_,
|
||||||
const hb_vector_t<DATA> &dataArray,
|
const DATA *dataArray,
|
||||||
|
unsigned int dataArrayLen,
|
||||||
const hb_vector_t<unsigned int> &dataSizeArray,
|
const hb_vector_t<unsigned int> &dataSizeArray,
|
||||||
const PARAM1 ¶m1,
|
const PARAM1 ¶m1,
|
||||||
const PARAM2 ¶m2)
|
const PARAM2 ¶m2)
|
||||||
|
@ -212,15 +213,15 @@ struct IndexOf : CFFIndex<COUNT>
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
/* serialize CFFIndex header */
|
/* serialize CFFIndex header */
|
||||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||||
this->count.set (dataArray.len);
|
this->count.set (dataArrayLen);
|
||||||
this->offSize.set (offSize_);
|
this->offSize.set (offSize_);
|
||||||
if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArray.len + 1))))
|
if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
/* serialize indices */
|
/* serialize indices */
|
||||||
unsigned int offset = 1;
|
unsigned int offset = 1;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
for (; i < dataArray.len; i++)
|
for (; i < dataArrayLen; i++)
|
||||||
{
|
{
|
||||||
CFFIndex<COUNT>::set_offset_at (i, offset);
|
CFFIndex<COUNT>::set_offset_at (i, offset);
|
||||||
offset += dataSizeArray[i];
|
offset += dataSizeArray[i];
|
||||||
|
@ -228,7 +229,7 @@ struct IndexOf : CFFIndex<COUNT>
|
||||||
CFFIndex<COUNT>::set_offset_at (i, offset);
|
CFFIndex<COUNT>::set_offset_at (i, offset);
|
||||||
|
|
||||||
/* serialize data */
|
/* serialize data */
|
||||||
for (unsigned int i = 0; i < dataArray.len; i++)
|
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||||
{
|
{
|
||||||
TYPE *dest = c->start_embed<TYPE> ();
|
TYPE *dest = c->start_embed<TYPE> ();
|
||||||
if (unlikely (dest == nullptr ||
|
if (unlikely (dest == nullptr ||
|
||||||
|
@ -241,13 +242,14 @@ struct IndexOf : CFFIndex<COUNT>
|
||||||
/* in parallel to above */
|
/* in parallel to above */
|
||||||
template <typename DATA, typename PARAM>
|
template <typename DATA, typename PARAM>
|
||||||
inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
|
inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
|
||||||
const hb_vector_t<DATA> &dataArray,
|
const DATA *dataArray,
|
||||||
|
unsigned int dataArrayLen,
|
||||||
hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
|
hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
|
||||||
const PARAM ¶m)
|
const PARAM ¶m)
|
||||||
{
|
{
|
||||||
/* determine offset size */
|
/* determine offset size */
|
||||||
unsigned int totalDataSize = 0;
|
unsigned int totalDataSize = 0;
|
||||||
for (unsigned int i = 0; i < dataArray.len; i++)
|
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||||
{
|
{
|
||||||
unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
|
unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
|
||||||
dataSizeArray[i] = dataSize;
|
dataSizeArray[i] = dataSize;
|
||||||
|
@ -255,7 +257,7 @@ struct IndexOf : CFFIndex<COUNT>
|
||||||
}
|
}
|
||||||
offSize_ = calcOffSize (totalDataSize);
|
offSize_ = calcOffSize (totalDataSize);
|
||||||
|
|
||||||
return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArray.len, totalDataSize);
|
return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -269,9 +271,9 @@ struct Dict : UnsizedByteStr
|
||||||
PARAM& param)
|
PARAM& param)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
for (unsigned int i = 0; i < dictval.values.len; i++)
|
for (unsigned int i = 0; i < dictval.getNumValues (); i++)
|
||||||
{
|
{
|
||||||
if (unlikely (!opszr.serialize (c, dictval.values[i], param)))
|
if (unlikely (!opszr.serialize (c, dictval[i], param)))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -283,8 +285,8 @@ struct Dict : UnsizedByteStr
|
||||||
OP_SERIALIZER& opszr)
|
OP_SERIALIZER& opszr)
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < dictval.values.len; i++)
|
for (unsigned int i = 0; i < dictval.getNumValues (); i++)
|
||||||
size += opszr.calculate_serialized_size (dictval.values[i]);
|
size += opszr.calculate_serialized_size (dictval[i]);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +370,7 @@ struct FDMap : hb_vector_t<hb_codepoint_t>
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename COUNT>
|
template <typename COUNT>
|
||||||
struct FDArray : IndexOf<COUNT, FontDict>
|
struct FDArray : CFFIndexOf<COUNT, FontDict>
|
||||||
{
|
{
|
||||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||||
inline bool serialize (hb_serialize_context_t *c,
|
inline bool serialize (hb_serialize_context_t *c,
|
||||||
|
@ -392,10 +394,10 @@ struct FDArray : IndexOf<COUNT, FontDict>
|
||||||
for (unsigned i = 0; i < fontDicts.len; i++)
|
for (unsigned i = 0; i < fontDicts.len; i++)
|
||||||
if (!fdmap.excludes (i))
|
if (!fdmap.excludes (i))
|
||||||
{
|
{
|
||||||
IndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
|
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
|
||||||
offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
|
offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
|
||||||
}
|
}
|
||||||
IndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||||
|
|
||||||
/* serialize font dicts */
|
/* serialize font dicts */
|
||||||
for (unsigned int i = 0; i < fontDicts.len; i++)
|
for (unsigned int i = 0; i < fontDicts.len; i++)
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-ot-cff1-table.hh"
|
||||||
|
|
||||||
|
/* SID to code */
|
||||||
|
static const uint8_t standard_encoding [] =
|
||||||
|
{
|
||||||
|
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
|
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
|
||||||
|
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
|
||||||
|
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
|
||||||
|
95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
||||||
|
111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
|
||||||
|
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177,
|
||||||
|
178, 179, 180, 182, 183, 184, 185, 186, 187, 188, 189, 191, 193, 194, 195, 196,
|
||||||
|
197, 198, 199, 200, 202, 203, 205, 206, 207, 208, 225, 227, 232, 233, 234, 235,
|
||||||
|
241, 245, 248, 249, 250, 251
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SID to code */
|
||||||
|
static const uint8_t expert_encoding [] =
|
||||||
|
{
|
||||||
|
0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 0, 189, 0, 0, 188, 0,
|
||||||
|
0, 0, 0, 190, 202, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 48,
|
||||||
|
49, 50, 51, 52, 53, 54, 55, 56, 57, 60, 61, 62, 63, 65, 66, 67,
|
||||||
|
68, 69, 73, 76, 77, 78, 79, 82, 83, 84, 86, 89, 90, 91, 93, 94,
|
||||||
|
95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
||||||
|
111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
|
||||||
|
161, 162, 163, 166, 167, 168, 169, 170, 172, 175, 178, 179, 182, 183, 184, 191,
|
||||||
|
192, 193, 194, 195, 196, 197, 200, 204, 205, 206, 207, 208, 209, 210, 211, 212,
|
||||||
|
213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
|
||||||
|
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
|
||||||
|
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
|
||||||
|
};
|
||||||
|
|
||||||
|
/* glyph ID to SID */
|
||||||
|
static const uint16_t expert_charset [] =
|
||||||
|
{
|
||||||
|
0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
|
||||||
|
239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
|
||||||
|
253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
|
||||||
|
267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282,
|
||||||
|
283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
|
||||||
|
299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
|
||||||
|
315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150,
|
||||||
|
164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
|
||||||
|
341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356,
|
||||||
|
357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
|
||||||
|
373, 374, 375, 376, 377, 378
|
||||||
|
};
|
||||||
|
|
||||||
|
/* glyph ID to SID */
|
||||||
|
static const uint16_t expert_subset_charset [] =
|
||||||
|
{
|
||||||
|
0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
|
||||||
|
243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
|
||||||
|
258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
|
||||||
|
300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326,
|
||||||
|
150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
|
||||||
|
340, 341, 342, 343, 344, 345, 346
|
||||||
|
};
|
||||||
|
|
||||||
|
hb_codepoint_t OT::cff1::lookup_standard_encoding (hb_codepoint_t sid)
|
||||||
|
{
|
||||||
|
if (sid < ARRAY_LENGTH (standard_encoding))
|
||||||
|
return (hb_codepoint_t)standard_encoding[sid];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_codepoint_t OT::cff1::lookup_expert_encoding (hb_codepoint_t sid)
|
||||||
|
{
|
||||||
|
if (sid < ARRAY_LENGTH (expert_encoding))
|
||||||
|
return (hb_codepoint_t)expert_encoding[sid];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_codepoint_t OT::cff1::lookup_expert_charset (hb_codepoint_t glyph)
|
||||||
|
{
|
||||||
|
if (glyph < ARRAY_LENGTH (expert_charset))
|
||||||
|
return (hb_codepoint_t)expert_charset[glyph];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_codepoint_t OT::cff1::lookup_expert_subset_charset (hb_codepoint_t glyph)
|
||||||
|
{
|
||||||
|
if (glyph < ARRAY_LENGTH (expert_subset_charset))
|
||||||
|
return (hb_codepoint_t)expert_subset_charset[glyph];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -38,8 +38,13 @@ namespace CFF {
|
||||||
*/
|
*/
|
||||||
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
|
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
|
||||||
|
|
||||||
|
#define CFF_UNDEF_CODE 0xFFFFFFFF
|
||||||
|
|
||||||
|
enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
|
||||||
|
enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
|
||||||
|
|
||||||
typedef CFFIndex<HBUINT16> CFF1Index;
|
typedef CFFIndex<HBUINT16> CFF1Index;
|
||||||
template <typename Type> struct CFF1IndexOf : IndexOf<HBUINT16, Type> {};
|
template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
|
||||||
|
|
||||||
typedef CFFIndex<HBUINT16> CFF1Index;
|
typedef CFFIndex<HBUINT16> CFF1Index;
|
||||||
typedef CFF1Index CFF1CharStrings;
|
typedef CFF1Index CFF1CharStrings;
|
||||||
|
@ -56,15 +61,14 @@ struct Encoding0 {
|
||||||
return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
|
return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_code (hb_codepoint_t glyph, hb_codepoint_t &code) const
|
inline hb_codepoint_t get_code (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
if (glyph < nCodes)
|
if (glyph < nCodes)
|
||||||
{
|
{
|
||||||
code = (hb_codepoint_t)codes[glyph];
|
return (hb_codepoint_t)codes[glyph];
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return CFF_UNDEF_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (void) const
|
inline unsigned int get_size (void) const
|
||||||
|
@ -99,19 +103,17 @@ struct Encoding1 {
|
||||||
return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
|
return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_code (hb_codepoint_t glyph, hb_codepoint_t &code) const
|
inline hb_codepoint_t get_code (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < nRanges; i++)
|
for (unsigned int i = 0; i < nRanges; i++)
|
||||||
{
|
{
|
||||||
if (glyph <= ranges[i].nLeft)
|
if (glyph <= ranges[i].nLeft)
|
||||||
{
|
{
|
||||||
code = (hb_codepoint_t)ranges[i].first + glyph;
|
return (hb_codepoint_t)ranges[i].first + glyph;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
glyph -= (ranges[i].nLeft + 1);
|
glyph -= (ranges[i].nLeft + 1);
|
||||||
}
|
}
|
||||||
|
return CFF_UNDEF_CODE;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HBUINT8 nRanges;
|
HBUINT8 nRanges;
|
||||||
|
@ -120,7 +122,7 @@ struct Encoding1 {
|
||||||
DEFINE_SIZE_ARRAY (1, ranges);
|
DEFINE_SIZE_ARRAY (1, ranges);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EncSupplement {
|
struct SuppEncoding {
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -140,27 +142,28 @@ struct CFF1SuppEncData {
|
||||||
return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
|
return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_code (hb_codepoint_t glyph, hb_codepoint_t &code) const
|
inline void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < nSups; i++)
|
for (unsigned int i = 0; i < nSups; i++)
|
||||||
if (glyph == supps[i].glyph)
|
if (sid == supps[i].glyph)
|
||||||
{
|
codes.push (supps[i].code);
|
||||||
code = supps[i].code;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (void) const
|
inline unsigned int get_size (void) const
|
||||||
{ return HBUINT8::static_size + EncSupplement::static_size * nSups; }
|
{ return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
|
||||||
|
|
||||||
HBUINT8 nSups;
|
HBUINT8 nSups;
|
||||||
EncSupplement supps[VAR];
|
SuppEncoding supps[VAR];
|
||||||
|
|
||||||
DEFINE_SIZE_ARRAY (1, supps);
|
DEFINE_SIZE_ARRAY (1, supps);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct code_pair
|
||||||
|
{
|
||||||
|
hb_codepoint_t code;
|
||||||
|
hb_codepoint_t glyph;
|
||||||
|
};
|
||||||
|
|
||||||
struct Encoding {
|
struct Encoding {
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
|
@ -176,7 +179,8 @@ struct Encoding {
|
||||||
return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
|
return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool serialize (hb_serialize_context_t *c, const Encoding &src, unsigned int num_glyphs)
|
/* serialize a fullset Encoding */
|
||||||
|
inline bool serialize (hb_serialize_context_t *c, const Encoding &src)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
unsigned int size = src.get_size ();
|
unsigned int size = src.get_size ();
|
||||||
|
@ -186,27 +190,104 @@ struct Encoding {
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int calculate_serialized_size (void) const
|
/* serialize a subset Encoding */
|
||||||
{ return get_size (); } // XXX: TODO
|
inline bool serialize (hb_serialize_context_t *c,
|
||||||
|
uint8_t format,
|
||||||
|
unsigned int enc_count,
|
||||||
|
const hb_vector_t<code_pair>& code_ranges,
|
||||||
|
const hb_vector_t<code_pair>& supp_codes)
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
Encoding *dest = c->extend_min (*this);
|
||||||
|
if (unlikely (dest == nullptr)) return_trace (false);
|
||||||
|
dest->format.set (format | ((supp_codes.len > 0)? 0x80: 0));
|
||||||
|
if (format == 0)
|
||||||
|
{
|
||||||
|
Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
|
||||||
|
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||||
|
fmt0->nCodes.set (enc_count);
|
||||||
|
unsigned int glyph = 0;
|
||||||
|
for (unsigned int i = 0; i < code_ranges.len; i++)
|
||||||
|
{
|
||||||
|
hb_codepoint_t code = code_ranges[i].code;
|
||||||
|
for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
|
||||||
|
fmt0->codes[glyph++].set (code++);
|
||||||
|
assert ((glyph <= 0x100) && (code <= 0x100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.len);
|
||||||
|
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||||
|
fmt1->nRanges.set (code_ranges.len);
|
||||||
|
for (unsigned int i = 0; i < code_ranges.len; i++)
|
||||||
|
{
|
||||||
|
assert ((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF));
|
||||||
|
fmt1->ranges[i].first.set (code_ranges[i].code);
|
||||||
|
fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (supp_codes.len > 0)
|
||||||
|
{
|
||||||
|
CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.len);
|
||||||
|
if (unlikely (suppData == nullptr)) return_trace (false);
|
||||||
|
suppData->nSups.set (supp_codes.len);
|
||||||
|
for (unsigned int i = 0; i < supp_codes.len; i++)
|
||||||
|
{
|
||||||
|
suppData->supps[i].code.set (supp_codes[i].code);
|
||||||
|
suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parallel to above: calculate the size of a subset Encoding */
|
||||||
|
static inline unsigned int calculate_serialized_size (
|
||||||
|
uint8_t format,
|
||||||
|
unsigned int enc_count,
|
||||||
|
unsigned int supp_count)
|
||||||
|
{
|
||||||
|
unsigned int size = min_size;
|
||||||
|
if (format == 0)
|
||||||
|
size += Encoding0::min_size + HBUINT8::static_size * enc_count;
|
||||||
|
else
|
||||||
|
size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
|
||||||
|
if (supp_count > 0)
|
||||||
|
size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (void) const
|
inline unsigned int get_size (void) const
|
||||||
{
|
{
|
||||||
unsigned int size = min_size;
|
unsigned int size = min_size;
|
||||||
if ((format & 0x7F) == 0)
|
if (table_format () == 0)
|
||||||
size += u.format0.get_size ();
|
size += u.format0.get_size ();
|
||||||
else
|
else
|
||||||
size += u.format1.get_size ();
|
size += u.format1.get_size ();
|
||||||
if ((format & 0x80) != 0)
|
if (has_supplement ())
|
||||||
size += suppEncData ().get_size ();
|
size += suppEncData ().get_size ();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_code (hb_codepoint_t glyph, hb_codepoint_t &code) const
|
inline hb_codepoint_t get_code (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
// XXX: TODO
|
if (table_format () == 0)
|
||||||
return false;
|
return u.format0.get_code (glyph);
|
||||||
|
else
|
||||||
|
return u.format1.get_code (glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint8_t table_format (void) const { return (format & 0x7F); }
|
||||||
|
inline bool has_supplement (void) const { return (format & 0x80) != 0; }
|
||||||
|
|
||||||
|
inline void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
|
||||||
|
{
|
||||||
|
codes.resize (0);
|
||||||
|
if (has_supplement ())
|
||||||
|
suppEncData().get_codes (sid, codes);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
inline const CFF1SuppEncData &suppEncData (void) const
|
inline const CFF1SuppEncData &suppEncData (void) const
|
||||||
{
|
{
|
||||||
if ((format & 0x7F) == 0)
|
if ((format & 0x7F) == 0)
|
||||||
|
@ -215,7 +296,9 @@ struct Encoding {
|
||||||
return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
|
return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
HBUINT8 format;
|
HBUINT8 format;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
Encoding0 format0;
|
Encoding0 format0;
|
||||||
Encoding1 format1;
|
Encoding1 format1;
|
||||||
|
@ -233,7 +316,7 @@ struct Charset0 {
|
||||||
return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
|
return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_sid (hb_codepoint_t glyph)
|
inline hb_codepoint_t get_sid (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
if (glyph == 0)
|
if (glyph == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -260,44 +343,69 @@ struct Charset_Range {
|
||||||
return_trace (c->check_struct (this));
|
return_trace (c->check_struct (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
HBUINT8 first;
|
HBUINT16 first;
|
||||||
TYPE nLeft;
|
TYPE nLeft;
|
||||||
|
|
||||||
DEFINE_SIZE_STATIC (1 + TYPE::static_size);
|
DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TYPE>
|
template <typename TYPE>
|
||||||
struct Charset1_2 {
|
struct Charset1_2 {
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
|
if (unlikely (!c->check_struct (this)))
|
||||||
|
return_trace (false);
|
||||||
|
num_glyphs--;
|
||||||
|
for (unsigned int i = 0; num_glyphs > 0; i++)
|
||||||
|
{
|
||||||
|
if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
|
||||||
|
return_trace (false);
|
||||||
|
num_glyphs -= (ranges[i].nLeft + 1);
|
||||||
|
}
|
||||||
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_sid (hb_codepoint_t glyph, unsigned int &sid) const
|
inline hb_codepoint_t get_sid (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < nRanges; i++)
|
if (glyph == 0) return 0;
|
||||||
|
glyph--;
|
||||||
|
for (unsigned int i = 0;; i++)
|
||||||
{
|
{
|
||||||
if (glyph <= ranges[i].nLeft)
|
if (glyph <= ranges[i].nLeft)
|
||||||
{
|
return (hb_codepoint_t)ranges[i].first + glyph;
|
||||||
sid = (hb_codepoint_t)ranges[i].first + glyph;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
glyph -= (ranges[i].nLeft + 1);
|
glyph -= (ranges[i].nLeft + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (void) const
|
inline unsigned int get_size (unsigned int num_glyphs) const
|
||||||
{ return HBUINT8::static_size + Charset_Range<TYPE>::static_size * nRanges; }
|
{
|
||||||
|
unsigned int size = HBUINT8::static_size;
|
||||||
|
int glyph = (int)num_glyphs;
|
||||||
|
|
||||||
|
assert (glyph > 0);
|
||||||
|
glyph--;
|
||||||
|
for (unsigned int i = 0; glyph > 0; i++)
|
||||||
|
{
|
||||||
|
glyph -= (ranges[i].nLeft + 1);
|
||||||
|
size += Charset_Range<TYPE>::static_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
HBUINT8 nRanges;
|
|
||||||
Charset_Range<TYPE> ranges[VAR];
|
Charset_Range<TYPE> ranges[VAR];
|
||||||
|
|
||||||
DEFINE_SIZE_ARRAY (1, ranges);
|
DEFINE_SIZE_ARRAY (0, ranges);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef Charset1_2<HBUINT8> Charset1;
|
||||||
|
typedef Charset1_2<HBUINT16> Charset2;
|
||||||
|
typedef Charset_Range<HBUINT8> Charset1_Range;
|
||||||
|
typedef Charset_Range<HBUINT16> Charset2_Range;
|
||||||
|
|
||||||
struct Charset {
|
struct Charset {
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
|
@ -308,13 +416,14 @@ struct Charset {
|
||||||
if (format == 0)
|
if (format == 0)
|
||||||
return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
|
return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
|
||||||
else if (format == 1)
|
else if (format == 1)
|
||||||
return_trace (u.format1.sanitize (c));
|
return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
|
||||||
else if (likely (format == 2))
|
else if (likely (format == 2))
|
||||||
return_trace (u.format2.sanitize (c));
|
return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
|
||||||
else
|
else
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* serialize a fullset Charset */
|
||||||
inline bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
|
inline bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
@ -325,8 +434,68 @@ struct Charset {
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int calculate_serialized_size (unsigned int num_glyphs) const
|
/* serialize a subset Charset */
|
||||||
{ return get_size (num_glyphs); } // XXX: TODO
|
inline bool serialize (hb_serialize_context_t *c,
|
||||||
|
uint8_t format,
|
||||||
|
unsigned int num_glyphs,
|
||||||
|
const hb_vector_t<code_pair>& sid_ranges)
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
Charset *dest = c->extend_min (*this);
|
||||||
|
if (unlikely (dest == nullptr)) return_trace (false);
|
||||||
|
dest->format.set (format);
|
||||||
|
if (format == 0)
|
||||||
|
{
|
||||||
|
Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT8::static_size * (num_glyphs - 1));
|
||||||
|
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||||
|
unsigned int glyph = 0;
|
||||||
|
for (unsigned int i = 0; i < sid_ranges.len; i++)
|
||||||
|
{
|
||||||
|
hb_codepoint_t sid = sid_ranges[i].code;
|
||||||
|
for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
|
||||||
|
fmt0->sids[glyph++].set (sid++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (format == 1)
|
||||||
|
{
|
||||||
|
Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.len);
|
||||||
|
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||||
|
for (unsigned int i = 0; i < sid_ranges.len; i++)
|
||||||
|
{
|
||||||
|
assert (sid_ranges[i].glyph <= 0xFF);
|
||||||
|
fmt1->ranges[i].first.set (sid_ranges[i].code);
|
||||||
|
fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* format 2 */
|
||||||
|
{
|
||||||
|
Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.len);
|
||||||
|
if (unlikely (fmt2 == nullptr)) return_trace (false);
|
||||||
|
for (unsigned int i = 0; i < sid_ranges.len; i++)
|
||||||
|
{
|
||||||
|
assert (sid_ranges[i].glyph <= 0xFFFF);
|
||||||
|
fmt2->ranges[i].first.set (sid_ranges[i].code);
|
||||||
|
fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parallel to above: calculate the size of a subset Charset */
|
||||||
|
static inline unsigned int calculate_serialized_size (
|
||||||
|
uint8_t format,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
unsigned int size = min_size;
|
||||||
|
if (format == 0)
|
||||||
|
size += Charset0::min_size + HBUINT8::static_size * (count - 1);
|
||||||
|
else if (format == 1)
|
||||||
|
size += Charset1::min_size + Charset1_Range::static_size * count;
|
||||||
|
else
|
||||||
|
size += Charset2::min_size + Charset2_Range::static_size * count;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (unsigned int num_glyphs) const
|
inline unsigned int get_size (unsigned int num_glyphs) const
|
||||||
{
|
{
|
||||||
|
@ -334,23 +503,27 @@ struct Charset {
|
||||||
if (format == 0)
|
if (format == 0)
|
||||||
size += u.format0.get_size (num_glyphs);
|
size += u.format0.get_size (num_glyphs);
|
||||||
else if (format == 1)
|
else if (format == 1)
|
||||||
size += u.format1.get_size ();
|
size += u.format1.get_size (num_glyphs);
|
||||||
else
|
else
|
||||||
size += u.format2.get_size ();
|
size += u.format2.get_size (num_glyphs);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_sid (hb_codepoint_t glyph, unsigned int &sid) const
|
inline hb_codepoint_t get_sid (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
// XXX: TODO
|
if (format == 0)
|
||||||
return false;
|
return u.format0.get_sid (glyph);
|
||||||
|
else if (format == 1)
|
||||||
|
return u.format1.get_sid (glyph);
|
||||||
|
else
|
||||||
|
return u.format2.get_sid (glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
HBUINT8 format;
|
HBUINT8 format;
|
||||||
union {
|
union {
|
||||||
Charset0 format0;
|
Charset0 format0;
|
||||||
Charset1_2<HBUINT8> format1;
|
Charset1 format1;
|
||||||
Charset1_2<HBUINT16> format2;
|
Charset2 format2;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
DEFINE_SIZE_MIN (1);
|
DEFINE_SIZE_MIN (1);
|
||||||
|
@ -381,16 +554,16 @@ struct CFF1TopDictValues : TopDictValues
|
||||||
inline unsigned int calculate_serialized_size (void) const
|
inline unsigned int calculate_serialized_size (void) const
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < values.len; i++)
|
for (unsigned int i = 0; i < getNumValues (); i++)
|
||||||
{
|
{
|
||||||
OpCode op = values[i].op;
|
OpCode op = getValue (i).op;
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OpCode_FDSelect:
|
case OpCode_FDSelect:
|
||||||
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
size += TopDictValues::calculate_serialized_op_size (values[i]);
|
size += TopDictValues::calculate_serialized_op_size (getValue (i));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,13 +573,44 @@ struct CFF1TopDictValues : TopDictValues
|
||||||
unsigned int ros[3]; /* registry, ordering, supplement */
|
unsigned int ros[3]; /* registry, ordering, supplement */
|
||||||
unsigned int cidCount;
|
unsigned int cidCount;
|
||||||
|
|
||||||
enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
|
|
||||||
unsigned int EncodingOffset;
|
unsigned int EncodingOffset;
|
||||||
unsigned int CharsetOffset;
|
unsigned int CharsetOffset;
|
||||||
unsigned int FDSelectOffset;
|
unsigned int FDSelectOffset;
|
||||||
TableInfo privateDictInfo;
|
TableInfo privateDictInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* a copy of a parsed out CFF1TopDictValues augmented with additional operators */
|
||||||
|
struct CFF1TopDictValuesMod : CFF1TopDictValues
|
||||||
|
{
|
||||||
|
inline void init (const CFF1TopDictValues *base_= &Null(CFF1TopDictValues))
|
||||||
|
{
|
||||||
|
SUPER::init ();
|
||||||
|
base = base_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
SUPER::fini ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned getNumValues (void) const
|
||||||
|
{
|
||||||
|
return base->getNumValues () + SUPER::getNumValues ();
|
||||||
|
}
|
||||||
|
inline const OpStr &getValue (unsigned int i) const
|
||||||
|
{
|
||||||
|
if (i < base->getNumValues ())
|
||||||
|
return (*base)[i];
|
||||||
|
else
|
||||||
|
return SUPER::values[i - base->getNumValues ()];
|
||||||
|
}
|
||||||
|
inline const OpStr &operator [] (unsigned int i) const { return getValue (i); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef CFF1TopDictValues SUPER;
|
||||||
|
const CFF1TopDictValues *base;
|
||||||
|
};
|
||||||
|
|
||||||
struct CFF1TopDictOpSet : TopDictOpSet
|
struct CFF1TopDictOpSet : TopDictOpSet
|
||||||
{
|
{
|
||||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1TopDictValues& dictval)
|
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1TopDictValues& dictval)
|
||||||
|
@ -488,7 +692,7 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -534,7 +738,7 @@ struct CFF1FontDictOpSet : DictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -557,11 +761,11 @@ struct CFF1PrivateDictValues_Base : DictValues<VAL>
|
||||||
inline unsigned int calculate_serialized_size (void) const
|
inline unsigned int calculate_serialized_size (void) const
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < DictValues<VAL>::values.len; i++)
|
for (unsigned int i = 0; i < DictValues<VAL>::getNumValues; i++)
|
||||||
if (DictValues<VAL>::values[i].op == OpCode_Subrs)
|
if (DictValues<VAL>::getValue (i).op == OpCode_Subrs)
|
||||||
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
||||||
else
|
else
|
||||||
size += DictValues<VAL>::values[i].str.len;
|
size += DictValues<VAL>::getValue (i).str.len;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +821,7 @@ struct CFF1PrivateDictOpSet : DictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr, val);
|
dictval.addOp (op, env.substr, val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -660,7 +864,7 @@ struct CFF1PrivateDictOpSet_Subset : DictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -730,6 +934,8 @@ struct cff1
|
||||||
|
|
||||||
encoding = &Null(Encoding);
|
encoding = &Null(Encoding);
|
||||||
charset = &StructAtOffsetOrNull<Charset> (cff, topDicts[0].CharsetOffset);
|
charset = &StructAtOffsetOrNull<Charset> (cff, topDicts[0].CharsetOffset);
|
||||||
|
if (unlikely (is_CID () && (charset == &Null(Charset))))
|
||||||
|
{ fini (); return; }
|
||||||
|
|
||||||
fdCount = 1;
|
fdCount = 1;
|
||||||
if (is_CID ())
|
if (is_CID ())
|
||||||
|
@ -746,8 +952,7 @@ struct cff1
|
||||||
{
|
{
|
||||||
fdArray = &Null(CFF1FDArray);
|
fdArray = &Null(CFF1FDArray);
|
||||||
fdSelect = &Null(CFF1FDSelect);
|
fdSelect = &Null(CFF1FDSelect);
|
||||||
if (topDicts[0].EncodingOffset != CFF1TopDictValues::StandardEncoding &&
|
if (!is_predef_encoding ())
|
||||||
topDicts[0].EncodingOffset != CFF1TopDictValues::ExpertEncoding)
|
|
||||||
{
|
{
|
||||||
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDicts[0].EncodingOffset);
|
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDicts[0].EncodingOffset);
|
||||||
if ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))
|
if ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))
|
||||||
|
@ -833,6 +1038,58 @@ struct cff1
|
||||||
inline bool is_valid (void) const { return blob != nullptr; }
|
inline bool is_valid (void) const { return blob != nullptr; }
|
||||||
inline bool is_CID (void) const { return topDicts[0].is_CID (); }
|
inline bool is_CID (void) const { return topDicts[0].is_CID (); }
|
||||||
|
|
||||||
|
inline bool is_predef_encoding (void) const { return topDicts[0].EncodingOffset <= ExpertEncoding; }
|
||||||
|
inline bool is_predef_charset (void) const { return topDicts[0].CharsetOffset <= ExpertSubsetCharset; }
|
||||||
|
|
||||||
|
inline hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
|
||||||
|
{
|
||||||
|
if (encoding != &Null(Encoding))
|
||||||
|
return encoding->get_code (glyph);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hb_codepoint_t sid = glyph_to_sid (glyph);
|
||||||
|
if (sid == 0) return 0;
|
||||||
|
hb_codepoint_t code = 0;
|
||||||
|
switch (topDicts[0].EncodingOffset)
|
||||||
|
{
|
||||||
|
case StandardEncoding:
|
||||||
|
code = lookup_standard_encoding (sid);
|
||||||
|
break;
|
||||||
|
case ExpertEncoding:
|
||||||
|
code = lookup_expert_encoding (sid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
|
||||||
|
{
|
||||||
|
if (charset != &Null(Charset))
|
||||||
|
return charset->get_sid (glyph);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hb_codepoint_t sid = 0;
|
||||||
|
switch (topDicts[0].CharsetOffset)
|
||||||
|
{
|
||||||
|
case ISOAdobeCharset:
|
||||||
|
if (glyph <= 228 /*zcaron*/) sid = glyph;
|
||||||
|
break;
|
||||||
|
case ExpertCharset:
|
||||||
|
sid = lookup_expert_charset (glyph);
|
||||||
|
break;
|
||||||
|
case ExpertSubsetCharset:
|
||||||
|
sid = lookup_expert_subset_charset (glyph);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline bool get_extents (hb_codepoint_t glyph,
|
inline bool get_extents (hb_codepoint_t glyph,
|
||||||
hb_glyph_extents_t *extents) const
|
hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
|
@ -884,6 +1141,12 @@ struct cff1
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static hb_codepoint_t lookup_standard_encoding (hb_codepoint_t sid);
|
||||||
|
static hb_codepoint_t lookup_expert_encoding (hb_codepoint_t sid);
|
||||||
|
static hb_codepoint_t lookup_expert_charset (hb_codepoint_t glyph);
|
||||||
|
static hb_codepoint_t lookup_expert_subset_charset (hb_codepoint_t glyph);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
|
FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
|
||||||
OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
|
OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace CFF {
|
||||||
#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
|
#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
|
||||||
|
|
||||||
typedef CFFIndex<HBUINT32> CFF2Index;
|
typedef CFFIndex<HBUINT32> CFF2Index;
|
||||||
template <typename Type> struct CFF2IndexOf : IndexOf<HBUINT32, Type> {};
|
template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
|
||||||
|
|
||||||
typedef CFF2Index CFF2CharStrings;
|
typedef CFF2Index CFF2CharStrings;
|
||||||
typedef FDArray<HBUINT32> CFF2FDArray;
|
typedef FDArray<HBUINT32> CFF2FDArray;
|
||||||
|
@ -152,9 +152,9 @@ struct CFF2TopDictValues : TopDictValues
|
||||||
inline unsigned int calculate_serialized_size (void) const
|
inline unsigned int calculate_serialized_size (void) const
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < values.len; i++)
|
for (unsigned int i = 0; i < getNumValues (); i++)
|
||||||
{
|
{
|
||||||
OpCode op = values[i].op;
|
OpCode op = getValue (i).op;
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OpCode_vstore:
|
case OpCode_vstore:
|
||||||
|
@ -162,7 +162,7 @@ struct CFF2TopDictValues : TopDictValues
|
||||||
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
size += TopDictValues::calculate_serialized_op_size (values[i]);
|
size += TopDictValues::calculate_serialized_op_size (getValue (i));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ struct CFF2TopDictOpSet : TopDictOpSet
|
||||||
{
|
{
|
||||||
DictVal val;
|
DictVal val;
|
||||||
val.init ();
|
val.init ();
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
env.clear_args ();
|
env.clear_args ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -205,7 +205,7 @@ struct CFF2TopDictOpSet : TopDictOpSet
|
||||||
if (!env.argStack.is_empty ()) return true;
|
if (!env.argStack.is_empty ()) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ struct CFF2FontDictOpSet : DictOpSet
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,11 +275,11 @@ struct CFF2PrivateDictValues_Base : DictValues<VAL>
|
||||||
inline unsigned int calculate_serialized_size (void) const
|
inline unsigned int calculate_serialized_size (void) const
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < DictValues<VAL>::values.len; i++)
|
for (unsigned int i = 0; i < DictValues<VAL>::getNumValues; i++)
|
||||||
if (DictValues<VAL>::values[i].op == OpCode_Subrs)
|
if (DictValues<VAL>::getValue (i).op == OpCode_Subrs)
|
||||||
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
||||||
else
|
else
|
||||||
size += DictValues<VAL>::values[i].str.len;
|
size += DictValues<VAL>::getValue (i).str.len;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr, val);
|
dictval.addOp (op, env.substr, val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -382,7 +382,7 @@ struct CFF2PrivateDictOpSet_Subset : DictOpSet
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictval.pushVal (op, env.substr);
|
dictval.addOp (op, env.substr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,40 +186,187 @@ struct cff_subset_plan {
|
||||||
inline cff_subset_plan (void)
|
inline cff_subset_plan (void)
|
||||||
: final_size (0),
|
: final_size (0),
|
||||||
orig_fdcount (0),
|
orig_fdcount (0),
|
||||||
subst_fdcount (1),
|
subset_fdcount (1),
|
||||||
subst_fdselect_format (0),
|
subset_fdselect_format (0),
|
||||||
offsets (),
|
offsets (),
|
||||||
flatten_subrs (true),
|
flatten_subrs (true),
|
||||||
drop_hints (false)
|
drop_hints (false)
|
||||||
{
|
{
|
||||||
topdict_sizes.init ();
|
topdict_sizes.init ();
|
||||||
topdict_sizes.resize (1);
|
topdict_sizes.resize (1);
|
||||||
subst_fdselect_first_glyphs.init ();
|
topdict_mod.init ();
|
||||||
|
subset_fdselect_first_glyphs.init ();
|
||||||
fdmap.init ();
|
fdmap.init ();
|
||||||
subset_charstrings.init ();
|
subset_charstrings.init ();
|
||||||
flat_charstrings.init ();
|
flat_charstrings.init ();
|
||||||
privateDictInfos.init ();
|
privateDictInfos.init ();
|
||||||
subrRefMaps.init ();
|
subrRefMaps.init ();
|
||||||
|
subset_enc_code_ranges.init ();
|
||||||
|
subset_enc_supp_codes.init ();
|
||||||
|
subset_charset_ranges.init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~cff_subset_plan (void)
|
inline ~cff_subset_plan (void)
|
||||||
{
|
{
|
||||||
topdict_sizes.fini ();
|
topdict_sizes.fini ();
|
||||||
subst_fdselect_first_glyphs.fini ();
|
topdict_mod.fini ();
|
||||||
|
subset_fdselect_first_glyphs.fini ();
|
||||||
fdmap.fini ();
|
fdmap.fini ();
|
||||||
subset_charstrings.fini ();
|
subset_charstrings.fini ();
|
||||||
flat_charstrings.fini ();
|
flat_charstrings.fini ();
|
||||||
privateDictInfos.fini ();
|
privateDictInfos.fini ();
|
||||||
subrRefMaps.fini ();
|
subrRefMaps.fini ();
|
||||||
|
subset_enc_code_ranges.fini ();
|
||||||
|
subset_enc_supp_codes.init ();
|
||||||
|
subset_charset_ranges.fini ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
const Encoding *encoding = acc.encoding;
|
||||||
|
unsigned int size0, size1, supp_size;
|
||||||
|
hb_codepoint_t code, last_code = CFF_UNDEF_CODE;
|
||||||
|
hb_vector_t<hb_codepoint_t> supp_codes;
|
||||||
|
|
||||||
|
subset_enc_code_ranges.resize (0);
|
||||||
|
supp_size = 0;
|
||||||
|
supp_codes.init ();
|
||||||
|
|
||||||
|
subset_enc_num_codes = plan->glyphs.len - 1;
|
||||||
|
unsigned int glyph;
|
||||||
|
for (glyph = 1; glyph < plan->glyphs.len; glyph++)
|
||||||
|
{
|
||||||
|
hb_codepoint_t orig_glyph = plan->glyphs[glyph];
|
||||||
|
code = acc.glyph_to_code (orig_glyph);
|
||||||
|
if (code == CFF_UNDEF_CODE)
|
||||||
|
{
|
||||||
|
subset_enc_num_codes = glyph - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code != last_code + 1)
|
||||||
|
{
|
||||||
|
if (subset_enc_code_ranges.len > 0)
|
||||||
|
{
|
||||||
|
code_pair &pair = subset_enc_code_ranges[subset_enc_code_ranges.len - 1];
|
||||||
|
pair.glyph = glyph - pair.glyph - 1;
|
||||||
|
}
|
||||||
|
code_pair pair = { code, glyph };
|
||||||
|
subset_enc_code_ranges.push (pair);
|
||||||
|
}
|
||||||
|
last_code = code;
|
||||||
|
|
||||||
|
if (encoding != &Null(Encoding))
|
||||||
|
{
|
||||||
|
hb_codepoint_t sid = acc.glyph_to_sid (orig_glyph);
|
||||||
|
encoding->get_supplement_codes (sid, supp_codes);
|
||||||
|
for (unsigned int i = 0; i < supp_codes.len; i++)
|
||||||
|
{
|
||||||
|
code_pair pair = { supp_codes[i], sid };
|
||||||
|
subset_enc_supp_codes.push (pair);
|
||||||
|
}
|
||||||
|
supp_size += SuppEncoding::static_size * supp_codes.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
supp_codes.fini ();
|
||||||
|
if (subset_enc_code_ranges.len > 0)
|
||||||
|
{
|
||||||
|
code_pair &pair = subset_enc_code_ranges[subset_enc_code_ranges.len - 1];
|
||||||
|
pair.glyph = glyph - pair.glyph - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (subset_enc_num_codes <= 0xFF);
|
||||||
|
size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
|
||||||
|
size1 = Encoding1::min_size + Encoding1_Range::static_size * subset_enc_code_ranges.len;
|
||||||
|
|
||||||
|
if (size0 < size1)
|
||||||
|
subset_enc_format = 0;
|
||||||
|
else
|
||||||
|
subset_enc_format = 1;
|
||||||
|
|
||||||
|
return Encoding::calculate_serialized_size (
|
||||||
|
subset_enc_format,
|
||||||
|
subset_enc_format? subset_enc_code_ranges.len: subset_enc_num_codes,
|
||||||
|
subset_enc_supp_codes.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
const Charset *charset = acc.charset;
|
||||||
|
unsigned int size0, size_ranges;
|
||||||
|
hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE;
|
||||||
|
bool two_byte = false;
|
||||||
|
|
||||||
|
subset_charset_ranges.resize (0);
|
||||||
|
unsigned int glyph;
|
||||||
|
for (glyph = 1; glyph < plan->glyphs.len; glyph++)
|
||||||
|
{
|
||||||
|
hb_codepoint_t orig_glyph = plan->glyphs[glyph];
|
||||||
|
sid = acc.glyph_to_sid (orig_glyph);
|
||||||
|
|
||||||
|
if (sid != last_sid + 1)
|
||||||
|
{
|
||||||
|
if (subset_charset_ranges.len > 0)
|
||||||
|
{
|
||||||
|
code_pair &pair = subset_charset_ranges[subset_charset_ranges.len - 1];
|
||||||
|
pair.glyph = glyph - pair.glyph - 1;
|
||||||
|
if ((pair.glyph & ~0xFF) != 0) two_byte = true;
|
||||||
|
}
|
||||||
|
code_pair pair = { sid, glyph };
|
||||||
|
subset_charset_ranges.push (pair);
|
||||||
|
}
|
||||||
|
last_sid = sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subset_charset_ranges.len > 0)
|
||||||
|
{
|
||||||
|
code_pair &pair = subset_charset_ranges[subset_charset_ranges.len - 1];
|
||||||
|
pair.glyph = glyph - pair.glyph - 1;
|
||||||
|
if ((pair.glyph & ~0xFF) != 0) two_byte = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs.len - 1);
|
||||||
|
if (!two_byte)
|
||||||
|
size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.len;
|
||||||
|
else
|
||||||
|
size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.len;
|
||||||
|
|
||||||
|
if (size0 < size_ranges)
|
||||||
|
subset_charset_format = 0;
|
||||||
|
else if (!two_byte)
|
||||||
|
subset_charset_format = 1;
|
||||||
|
else
|
||||||
|
subset_charset_format = 2;
|
||||||
|
|
||||||
|
return Charset::calculate_serialized_size (
|
||||||
|
subset_charset_format,
|
||||||
|
subset_charset_format? subset_charset_ranges.len: plan->glyphs.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool create (const OT::cff1::accelerator_subset_t &acc,
|
inline bool create (const OT::cff1::accelerator_subset_t &acc,
|
||||||
hb_subset_plan_t *plan)
|
hb_subset_plan_t *plan)
|
||||||
{
|
{
|
||||||
|
/* make sure notdef is first */
|
||||||
|
if ((plan->glyphs.len == 0) || (plan->glyphs[0] != 0)) return false;
|
||||||
|
|
||||||
final_size = 0;
|
final_size = 0;
|
||||||
|
num_glyphs = plan->glyphs.len;
|
||||||
orig_fdcount = acc.fdCount;
|
orig_fdcount = acc.fdCount;
|
||||||
drop_hints = plan->drop_hints;
|
drop_hints = plan->drop_hints;
|
||||||
|
|
||||||
|
/* check whether the subset renumbers any glyph IDs */
|
||||||
|
gid_renum = false;
|
||||||
|
for (unsigned int glyph = 0; glyph < plan->glyphs.len; glyph++)
|
||||||
|
{
|
||||||
|
if (plan->glyphs[glyph] != glyph) {
|
||||||
|
gid_renum = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subset_charset = gid_renum || !acc.is_predef_charset ();
|
||||||
|
subset_encoding = !acc.is_CID() && (gid_renum || !acc.is_predef_encoding ());
|
||||||
|
|
||||||
/* CFF header */
|
/* CFF header */
|
||||||
final_size += OT::cff1::static_size;
|
final_size += OT::cff1::static_size;
|
||||||
|
|
||||||
|
@ -229,11 +376,24 @@ struct cff_subset_plan {
|
||||||
|
|
||||||
/* top dict INDEX */
|
/* top dict INDEX */
|
||||||
{
|
{
|
||||||
|
/* Add encoding/charset to a (copy of) top dict as necessary */
|
||||||
|
topdict_mod.init (&acc.topDicts[0]);
|
||||||
|
bool need_to_add_enc = (subset_encoding && !acc.topDicts[0].hasOp (OpCode_Encoding));
|
||||||
|
bool need_to_add_set = (subset_charset && !acc.topDicts[0].hasOp (OpCode_charset));
|
||||||
|
if (need_to_add_enc || need_to_add_set)
|
||||||
|
{
|
||||||
|
if (need_to_add_enc)
|
||||||
|
topdict_mod.addOp (OpCode_Encoding);
|
||||||
|
if (need_to_add_set)
|
||||||
|
topdict_mod.addOp (OpCode_charset);
|
||||||
|
}
|
||||||
offsets.topDictInfo.offset = final_size;
|
offsets.topDictInfo.offset = final_size;
|
||||||
CFF1TopDict_OpSerializer topSzr;
|
CFF1TopDict_OpSerializer topSzr;
|
||||||
unsigned int topDictSize = TopDict::calculate_serialized_size (acc.topDicts[0], topSzr);
|
unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
|
||||||
offsets.topDictInfo.offSize = calcOffSize(topDictSize);
|
offsets.topDictInfo.offSize = calcOffSize(topDictSize);
|
||||||
final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<CFF1TopDictValues> (offsets.topDictInfo.offSize, acc.topDicts, topdict_sizes, topSzr);
|
final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<CFF1TopDictValuesMod>
|
||||||
|
(offsets.topDictInfo.offSize,
|
||||||
|
&topdict_mod, 1, topdict_sizes, topSzr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* String INDEX */
|
/* String INDEX */
|
||||||
|
@ -270,13 +430,13 @@ struct cff_subset_plan {
|
||||||
|
|
||||||
/* Encoding */
|
/* Encoding */
|
||||||
offsets.encodingOffset = final_size;
|
offsets.encodingOffset = final_size;
|
||||||
if (acc.encoding != &Null(Encoding))
|
if (subset_encoding)
|
||||||
final_size += acc.encoding->get_size ();
|
final_size += plan_subset_encoding (acc, plan);
|
||||||
|
|
||||||
/* Charset */
|
/* Charset */
|
||||||
offsets.charsetOffset = final_size;
|
offsets.charsetOffset = final_size;
|
||||||
if (acc.charset != &Null(Charset))
|
if (subset_charset)
|
||||||
final_size += acc.charset->get_size (acc.num_glyphs);
|
final_size += plan_subset_charset (acc, plan);
|
||||||
|
|
||||||
/* FDSelect */
|
/* FDSelect */
|
||||||
if (acc.fdSelect != &Null(CFF1FDSelect))
|
if (acc.fdSelect != &Null(CFF1FDSelect))
|
||||||
|
@ -285,10 +445,10 @@ struct cff_subset_plan {
|
||||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||||
orig_fdcount,
|
orig_fdcount,
|
||||||
*acc.fdSelect,
|
*acc.fdSelect,
|
||||||
subst_fdcount,
|
subset_fdcount,
|
||||||
offsets.FDSelectInfo.size,
|
offsets.FDSelectInfo.size,
|
||||||
subst_fdselect_format,
|
subset_fdselect_format,
|
||||||
subst_fdselect_first_glyphs,
|
subset_fdselect_first_glyphs,
|
||||||
fdmap)))
|
fdmap)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -301,7 +461,7 @@ struct cff_subset_plan {
|
||||||
if (acc.fdArray != &Null(CFF1FDArray)) {
|
if (acc.fdArray != &Null(CFF1FDArray)) {
|
||||||
offsets.FDArrayInfo.offset = final_size;
|
offsets.FDArrayInfo.offset = final_size;
|
||||||
CFFFontDict_OpSerializer fontSzr;
|
CFFFontDict_OpSerializer fontSzr;
|
||||||
final_size += CFF1FDArray::calculate_serialized_size(offsets.FDArrayInfo.offSize/*OUT*/, acc.fontDicts, subst_fdcount, fdmap, fontSzr);
|
final_size += CFF1FDArray::calculate_serialized_size(offsets.FDArrayInfo.offSize/*OUT*/, acc.fontDicts, subset_fdcount, fdmap, fontSzr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CharStrings */
|
/* CharStrings */
|
||||||
|
@ -349,20 +509,22 @@ struct cff_subset_plan {
|
||||||
offsets.privateDictInfo = privateDictInfos[0];
|
offsets.privateDictInfo = privateDictInfos[0];
|
||||||
|
|
||||||
return ((subset_charstrings.len == plan->glyphs.len) &&
|
return ((subset_charstrings.len == plan->glyphs.len) &&
|
||||||
(privateDictInfos.len == subst_fdcount));
|
(privateDictInfos.len == subset_fdcount));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_final_size (void) const { return final_size; }
|
inline unsigned int get_final_size (void) const { return final_size; }
|
||||||
|
|
||||||
unsigned int final_size;
|
unsigned int final_size;
|
||||||
hb_vector_t<unsigned int> topdict_sizes;
|
hb_vector_t<unsigned int> topdict_sizes;
|
||||||
|
CFF1TopDictValuesMod topdict_mod;
|
||||||
CFF1SubTableOffsets offsets;
|
CFF1SubTableOffsets offsets;
|
||||||
|
|
||||||
|
unsigned int num_glyphs;
|
||||||
unsigned int orig_fdcount;
|
unsigned int orig_fdcount;
|
||||||
unsigned int subst_fdcount;
|
unsigned int subset_fdcount;
|
||||||
inline bool is_fds_subsetted (void) const { return subst_fdcount < orig_fdcount; }
|
inline bool is_fds_subsetted (void) const { return subset_fdcount < orig_fdcount; }
|
||||||
unsigned int subst_fdselect_format;
|
unsigned int subset_fdselect_format;
|
||||||
hb_vector_t<hb_codepoint_t> subst_fdselect_first_glyphs;
|
hb_vector_t<hb_codepoint_t> subset_fdselect_first_glyphs;
|
||||||
|
|
||||||
/* font dict index remap table from fullset FDArray to subset FDArray.
|
/* font dict index remap table from fullset FDArray to subset FDArray.
|
||||||
* set to HB_SET_VALUE_INVALID if excluded from subset */
|
* set to HB_SET_VALUE_INVALID if excluded from subset */
|
||||||
|
@ -376,6 +538,17 @@ struct cff_subset_plan {
|
||||||
|
|
||||||
bool flatten_subrs;
|
bool flatten_subrs;
|
||||||
bool drop_hints;
|
bool drop_hints;
|
||||||
|
|
||||||
|
bool gid_renum;
|
||||||
|
bool subset_encoding;
|
||||||
|
uint8_t subset_enc_format;
|
||||||
|
unsigned int subset_enc_num_codes;
|
||||||
|
hb_vector_t<code_pair> subset_enc_code_ranges;
|
||||||
|
hb_vector_t<code_pair> subset_enc_supp_codes;
|
||||||
|
|
||||||
|
uint8_t subset_charset_format;
|
||||||
|
hb_vector_t<code_pair> subset_charset_ranges;
|
||||||
|
bool subset_charset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool _write_cff1 (const cff_subset_plan &plan,
|
static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
|
@ -417,7 +590,9 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
|
CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
|
||||||
if (dest == nullptr) return false;
|
if (dest == nullptr) return false;
|
||||||
CFF1TopDict_OpSerializer topSzr;
|
CFF1TopDict_OpSerializer topSzr;
|
||||||
if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize, acc.topDicts, plan.topdict_sizes, topSzr, plan.offsets)))
|
if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
|
||||||
|
&plan.topdict_mod, 1,
|
||||||
|
plan.topdict_sizes, topSzr, plan.offsets)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
|
||||||
return false;
|
return false;
|
||||||
|
@ -450,11 +625,16 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encoding */
|
/* Encoding */
|
||||||
if (acc.encoding != &Null(Encoding)){
|
if (plan.subset_encoding)
|
||||||
|
{
|
||||||
assert (plan.offsets.encodingOffset == c.head - c.start);
|
assert (plan.offsets.encodingOffset == c.head - c.start);
|
||||||
Encoding *dest = c.start_embed<Encoding> ();
|
Encoding *dest = c.start_embed<Encoding> ();
|
||||||
if (unlikely (dest == nullptr)) return false;
|
if (unlikely (dest == nullptr)) return false;
|
||||||
if (unlikely (!dest->serialize (&c, *acc.encoding, acc.num_glyphs))) // XXX: TODO
|
if (unlikely (!dest->serialize (&c,
|
||||||
|
plan.subset_enc_format,
|
||||||
|
plan.subset_enc_num_codes,
|
||||||
|
plan.subset_enc_code_ranges,
|
||||||
|
plan.subset_enc_supp_codes)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
|
||||||
return false;
|
return false;
|
||||||
|
@ -462,12 +642,15 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Charset */
|
/* Charset */
|
||||||
if (acc.charset != &Null(Charset))
|
if (plan.subset_charset)
|
||||||
{
|
{
|
||||||
assert (plan.offsets.charsetOffset == c.head - c.start);
|
assert (plan.offsets.charsetOffset == c.head - c.start);
|
||||||
Charset *dest = c.start_embed<Charset> ();
|
Charset *dest = c.start_embed<Charset> ();
|
||||||
if (unlikely (dest == nullptr)) return false;
|
if (unlikely (dest == nullptr)) return false;
|
||||||
if (unlikely (!dest->serialize (&c, *acc.charset, acc.num_glyphs))) // XXX: TODO
|
if (unlikely (!dest->serialize (&c,
|
||||||
|
plan.subset_charset_format,
|
||||||
|
plan.num_glyphs,
|
||||||
|
plan.subset_charset_ranges)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
|
||||||
return false;
|
return false;
|
||||||
|
@ -482,8 +665,8 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
if (plan.is_fds_subsetted ())
|
if (plan.is_fds_subsetted ())
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs, *acc.fdSelect, acc.fdCount,
|
if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs, *acc.fdSelect, acc.fdCount,
|
||||||
plan.subst_fdselect_format, plan.offsets.FDSelectInfo.size,
|
plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
|
||||||
plan.subst_fdselect_first_glyphs,
|
plan.subset_fdselect_first_glyphs,
|
||||||
plan.fdmap)))
|
plan.fdmap)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
|
||||||
|
@ -509,7 +692,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||||
if (unlikely (fda == nullptr)) return false;
|
if (unlikely (fda == nullptr)) return false;
|
||||||
CFFFontDict_OpSerializer fontSzr;
|
CFFFontDict_OpSerializer fontSzr;
|
||||||
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
|
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
|
||||||
acc.fontDicts, plan.subst_fdcount, plan.fdmap,
|
acc.fontDicts, plan.subset_fdcount, plan.fdmap,
|
||||||
fontSzr, plan.privateDictInfos)))
|
fontSzr, plan.privateDictInfos)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
|
||||||
|
|
|
@ -197,12 +197,12 @@ struct cff2_subset_plan {
|
||||||
inline cff2_subset_plan (void)
|
inline cff2_subset_plan (void)
|
||||||
: final_size (0),
|
: final_size (0),
|
||||||
orig_fdcount (0),
|
orig_fdcount (0),
|
||||||
subst_fdcount(1),
|
subset_fdcount(1),
|
||||||
subst_fdselect_format (0),
|
subset_fdselect_format (0),
|
||||||
flatten_subrs (true),
|
flatten_subrs (true),
|
||||||
drop_hints (false)
|
drop_hints (false)
|
||||||
{
|
{
|
||||||
subst_fdselect_first_glyphs.init ();
|
subset_fdselect_first_glyphs.init ();
|
||||||
fdmap.init ();
|
fdmap.init ();
|
||||||
subset_charstrings.init ();
|
subset_charstrings.init ();
|
||||||
flat_charstrings.init ();
|
flat_charstrings.init ();
|
||||||
|
@ -212,7 +212,7 @@ struct cff2_subset_plan {
|
||||||
|
|
||||||
inline ~cff2_subset_plan (void)
|
inline ~cff2_subset_plan (void)
|
||||||
{
|
{
|
||||||
subst_fdselect_first_glyphs.fini ();
|
subset_fdselect_first_glyphs.fini ();
|
||||||
fdmap.fini ();
|
fdmap.fini ();
|
||||||
subset_charstrings.fini ();
|
subset_charstrings.fini ();
|
||||||
flat_charstrings.fini ();
|
flat_charstrings.fini ();
|
||||||
|
@ -281,10 +281,10 @@ struct cff2_subset_plan {
|
||||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||||
orig_fdcount,
|
orig_fdcount,
|
||||||
*(const FDSelect *)acc.fdSelect,
|
*(const FDSelect *)acc.fdSelect,
|
||||||
subst_fdcount,
|
subset_fdcount,
|
||||||
offsets.FDSelectInfo.size,
|
offsets.FDSelectInfo.size,
|
||||||
subst_fdselect_format,
|
subset_fdselect_format,
|
||||||
subst_fdselect_first_glyphs,
|
subset_fdselect_first_glyphs,
|
||||||
fdmap)))
|
fdmap)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ struct cff2_subset_plan {
|
||||||
{
|
{
|
||||||
offsets.FDArrayInfo.offset = final_size;
|
offsets.FDArrayInfo.offset = final_size;
|
||||||
CFFFontDict_OpSerializer fontSzr;
|
CFFFontDict_OpSerializer fontSzr;
|
||||||
final_size += CFF2FDArray::calculate_serialized_size(offsets.FDArrayInfo.offSize/*OUT*/, acc.fontDicts, subst_fdcount, fdmap, fontSzr);
|
final_size += CFF2FDArray::calculate_serialized_size(offsets.FDArrayInfo.offSize/*OUT*/, acc.fontDicts, subset_fdcount, fdmap, fontSzr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CharStrings */
|
/* CharStrings */
|
||||||
|
@ -350,10 +350,10 @@ struct cff2_subset_plan {
|
||||||
CFF2SubTableOffsets offsets;
|
CFF2SubTableOffsets offsets;
|
||||||
|
|
||||||
unsigned int orig_fdcount;
|
unsigned int orig_fdcount;
|
||||||
unsigned int subst_fdcount;
|
unsigned int subset_fdcount;
|
||||||
inline bool is_fds_subsetted (void) const { return subst_fdcount < orig_fdcount; }
|
inline bool is_fds_subsetted (void) const { return subset_fdcount < orig_fdcount; }
|
||||||
unsigned int subst_fdselect_format;
|
unsigned int subset_fdselect_format;
|
||||||
hb_vector_t<hb_codepoint_t> subst_fdselect_first_glyphs;
|
hb_vector_t<hb_codepoint_t> subset_fdselect_first_glyphs;
|
||||||
|
|
||||||
FDMap fdmap;
|
FDMap fdmap;
|
||||||
|
|
||||||
|
@ -429,8 +429,8 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
|
||||||
if (plan.is_fds_subsetted ())
|
if (plan.is_fds_subsetted ())
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
|
if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
|
||||||
plan.subst_fdselect_format, plan.offsets.FDSelectInfo.size,
|
plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
|
||||||
plan.subst_fdselect_first_glyphs,
|
plan.subset_fdselect_first_glyphs,
|
||||||
plan.fdmap)))
|
plan.fdmap)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
|
||||||
|
@ -455,7 +455,7 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
|
||||||
if (unlikely (fda == nullptr)) return false;
|
if (unlikely (fda == nullptr)) return false;
|
||||||
CFFFontDict_OpSerializer fontSzr;
|
CFFFontDict_OpSerializer fontSzr;
|
||||||
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
|
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
|
||||||
acc.fontDicts, plan.subst_fdcount, plan.fdmap,
|
acc.fontDicts, plan.subset_fdcount, plan.fdmap,
|
||||||
fontSzr, plan.privateDictInfos)))
|
fontSzr, plan.privateDictInfos)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
|
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
|
||||||
|
|
Loading…
Reference in New Issue