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:
Michiharu Ariza 2018-09-06 17:28:15 -07:00
parent 5ea03d2951
commit aca73c9df2
8 changed files with 737 additions and 147 deletions

View File

@ -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 \

View File

@ -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;
}; };

View File

@ -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 &param1, const PARAM1 &param1,
const PARAM2 &param2) const PARAM2 &param2)
@ -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 &param) const PARAM &param)
{ {
/* 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++)

130
src/hb-ot-cff1-table.cc Normal file
View File

@ -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;
}

View File

@ -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. */

View File

@ -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;
} }

View File

@ -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");

View File

@ -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");