summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc938
1 files changed, 406 insertions, 532 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
index e9e075749e..e9dd5d6427 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-cff1.cc
@@ -32,61 +32,80 @@
#include "hb-ot-cff1-table.hh"
#include "hb-set.h"
#include "hb-bimap.hh"
-#include "hb-subset-cff1.hh"
#include "hb-subset-plan.hh"
#include "hb-subset-cff-common.hh"
#include "hb-cff1-interp-cs.hh"
using namespace CFF;
-struct remap_sid_t : hb_inc_bimap_t
+struct remap_sid_t
{
+ unsigned get_population () const { return vector.length; }
+
+ void alloc (unsigned size)
+ {
+ map.alloc (size);
+ vector.alloc (size, true);
+ }
+
+ bool in_error () const
+ { return map.in_error () || vector.in_error (); }
+
unsigned int add (unsigned int sid)
{
- if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
- return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid)));
- else
+ if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
return sid;
+
+ sid = unoffset_sid (sid);
+ unsigned v = next;
+ if (map.set (sid, v, false))
+ {
+ vector.push (sid);
+ next++;
+ }
+ else
+ v = map.get (sid); // already exists
+ return offset_sid (v);
}
unsigned int operator[] (unsigned int sid) const
{
- if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+ if (is_std_str (sid) || (sid == CFF_UNDEF_SID))
return sid;
- else
- return offset_sid (get (unoffset_sid (sid)));
+
+ return offset_sid (map.get (unoffset_sid (sid)));
}
static const unsigned int num_std_strings = 391;
- static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+ static bool is_std_str (unsigned int sid) { return sid < num_std_strings; }
static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+ unsigned next = 0;
+
+ hb_map_t map;
+ hb_vector_t<unsigned> vector;
};
-struct cff1_sub_table_offsets_t : cff_sub_table_offsets_t
+struct cff1_sub_table_info_t : cff_sub_table_info_t
{
- cff1_sub_table_offsets_t ()
- : cff_sub_table_offsets_t (),
- nameIndexOffset (0),
- encodingOffset (0)
- {
- stringIndexInfo.init ();
- charsetInfo.init ();
+ cff1_sub_table_info_t ()
+ : cff_sub_table_info_t (),
+ encoding_link (0),
+ charset_link (0)
+ {
privateDictInfo.init ();
}
- unsigned int nameIndexOffset;
- table_info_t stringIndexInfo;
- unsigned int encodingOffset;
- table_info_t charsetInfo;
+ objidx_t encoding_link;
+ objidx_t charset_link;
table_info_t privateDictInfo;
};
/* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
{
- void init (const cff1_top_dict_values_t *base_= &Null(cff1_top_dict_values_t))
+ void init (const cff1_top_dict_values_t *base_= &Null (cff1_top_dict_values_t))
{
SUPER::init ();
base = base_;
@@ -117,13 +136,13 @@ struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
struct top_dict_modifiers_t
{
- top_dict_modifiers_t (const cff1_sub_table_offsets_t &offsets_,
- const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
- : offsets (offsets_),
+ top_dict_modifiers_t (const cff1_sub_table_info_t &info_,
+ const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
+ : info (info_),
nameSIDs (nameSIDs_)
{}
- const cff1_sub_table_offsets_t &offsets;
+ const cff1_sub_table_info_t &info;
const unsigned int (&nameSIDs)[name_dict_values_t::ValCount];
};
@@ -139,22 +158,20 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
switch (op)
{
case OpCode_charset:
- return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
+ if (mod.info.charset_link)
+ return_trace (FontDict::serialize_link4_op(c, op, mod.info.charset_link, whence_t::Absolute));
+ else
+ goto fall_back;
case OpCode_Encoding:
- return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
+ if (mod.info.encoding_link)
+ return_trace (FontDict::serialize_link4_op(c, op, mod.info.encoding_link, whence_t::Absolute));
+ else
+ goto fall_back;
case OpCode_Private:
- {
- if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
- return_trace (false);
- if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
- return_trace (false);
- HBUINT8 *p = c->allocate_size<HBUINT8> (1);
- if (unlikely (p == nullptr)) return_trace (false);
- *p = OpCode_Private;
- }
- break;
+ return_trace (UnsizedByteStr::serialize_int2 (c, mod.info.privateDictInfo.size) &&
+ Dict::serialize_link4_op (c, op, mod.info.privateDictInfo.link, whence_t::Absolute));
case OpCode_version:
case OpCode_Notice:
@@ -165,7 +182,7 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
case OpCode_PostScript:
case OpCode_BaseFontName:
case OpCode_FontName:
- return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
+ return_trace (FontDict::serialize_int2_op (c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
case OpCode_ROS:
{
@@ -173,93 +190,37 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
* for supplement, the original byte string is copied along with the op code */
op_str_t supp_op;
supp_op.op = op;
- if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+ if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
return_trace (false);
- supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+ supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
+ supp_op.length = opstr.length - opstr.last_arg_offset;
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
}
+ fall_back:
default:
- return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.offsets));
+ return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.info));
}
return_trace (true);
}
- unsigned int calculate_serialized_size (const cff1_top_dict_val_t &opstr) const
- {
- op_code_t op = opstr.op;
- switch (op)
- {
- case OpCode_charset:
- case OpCode_Encoding:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
-
- case OpCode_Private:
- return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
-
- case OpCode_version:
- case OpCode_Notice:
- case OpCode_Copyright:
- case OpCode_FullName:
- case OpCode_FamilyName:
- case OpCode_Weight:
- case OpCode_PostScript:
- case OpCode_BaseFontName:
- case OpCode_FontName:
- return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
-
- case OpCode_ROS:
- return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.length - opstr.last_arg_offset)/* supplement + op */;
-
- default:
- return cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::calculate_serialized_size (opstr);
- }
- }
-};
-
-struct font_dict_values_mod_t
-{
- void init (const cff1_font_dict_values_t *base_,
- unsigned int fontName_,
- const table_info_t &privateDictInfo_)
- {
- base = base_;
- fontName = fontName_;
- privateDictInfo = privateDictInfo_;
- }
-
- unsigned get_count () const { return base->get_count (); }
-
- const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
-
- const cff1_font_dict_values_t *base;
- table_info_t privateDictInfo;
- unsigned int fontName;
};
struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
{
bool serialize (hb_serialize_context_t *c,
const op_str_t &opstr,
- const font_dict_values_mod_t &mod) const
+ const cff1_font_dict_values_mod_t &mod) const
{
TRACE_SERIALIZE (this);
if (opstr.op == OpCode_FontName)
- return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
+ return_trace (FontDict::serialize_int2_op (c, opstr.op, mod.fontName));
else
return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
}
- unsigned int calculate_serialized_size (const op_str_t &opstr) const
- {
- if (opstr.op == OpCode_FontName)
- return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
- else
- return SUPER::calculate_serialized_size (opstr);
- }
-
private:
typedef cff_font_dict_op_serializer_t SUPER;
};
@@ -296,7 +257,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
{
str_encoder_t encoder (param.flatStr);
for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
- encoder.encode_num (env.eval_arg (i));
+ encoder.encode_num_cs (env.eval_arg (i));
SUPER::flush_args (env, param);
}
@@ -310,7 +271,7 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
{
assert (env.has_width);
str_encoder_t encoder (param.flatStr);
- encoder.encode_num (env.width);
+ encoder.encode_num_cs (env.width);
}
static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
@@ -331,18 +292,19 @@ struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatte
struct range_list_t : hb_vector_t<code_pair_t>
{
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
- bool finalize (unsigned int last_glyph)
+ bool complete (unsigned int last_glyph)
{
- bool two_byte = false;
- for (unsigned int i = (*this).length; i > 0; i--)
+ hb_codepoint_t all_glyphs = 0;
+ unsigned count = this->length;
+ for (unsigned int i = count; i; i--)
{
- code_pair_t &pair = (*this)[i - 1];
- unsigned int nLeft = last_glyph - pair.glyph - 1;
- if (nLeft >= 0x100)
- two_byte = true;
+ code_pair_t &pair = arrayZ[i - 1];
+ unsigned int nLeft = last_glyph - pair.glyph - 1;
+ all_glyphs |= nLeft;
last_glyph = pair.glyph;
pair.glyph = nLeft;
}
+ bool two_byte = all_glyphs >= 0x100;
return two_byte;
}
};
@@ -397,12 +359,42 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t
typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
};
+struct cff1_private_dict_op_serializer_t : op_serializer_t
+{
+ cff1_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
+ : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
+
+ bool serialize (hb_serialize_context_t *c,
+ const op_str_t &opstr,
+ objidx_t subrs_link) const
+ {
+ TRACE_SERIALIZE (this);
+
+ if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+ return_trace (true);
+
+ if (opstr.op == OpCode_Subrs)
+ {
+ if (desubroutinize || !subrs_link)
+ return_trace (true);
+ else
+ return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
+ }
+
+ return_trace (copy_opstr (c, opstr));
+ }
+
+ protected:
+ const bool desubroutinize;
+ const bool drop_hints;
+};
+
struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar>
{
cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* insert width at the beginning of the charstring as necessary */
if (env.has_width)
@@ -414,8 +406,8 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
param.current_parsed_str->set_parsed ();
for (unsigned int i = 0; i < env.callStack.get_count (); i++)
{
- parsed_cs_str_t *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
- if (likely (parsed_str != nullptr))
+ parsed_cs_str_t *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
+ if (likely (parsed_str))
parsed_str->set_parsed ();
else
env.set_error ();
@@ -423,99 +415,71 @@ struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs
}
};
-struct cff_subset_plan {
- cff_subset_plan ()
- : final_size (0),
- offsets (),
- orig_fdcount (0),
- subset_fdcount (1),
- subset_fdselect_format (0),
- drop_hints (false),
- desubroutinize(false)
+namespace OT {
+struct cff1_subset_plan
+{
+ cff1_subset_plan ()
{
- topdict_sizes.init ();
- topdict_sizes.resize (1);
- topdict_mod.init ();
- subset_fdselect_ranges.init ();
- fdmap.init ();
- subset_charstrings.init ();
- subset_globalsubrs.init ();
- subset_localsubrs.init ();
- fontdicts_mod.init ();
- subset_enc_code_ranges.init ();
- subset_enc_supp_codes.init ();
- subset_charset_ranges.init ();
- sidmap.init ();
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
topDictModSIDs[i] = CFF_UNDEF_SID;
}
- ~cff_subset_plan ()
- {
- topdict_sizes.fini ();
- topdict_mod.fini ();
- subset_fdselect_ranges.fini ();
- fdmap.fini ();
- subset_charstrings.fini_deep ();
- subset_globalsubrs.fini_deep ();
- subset_localsubrs.fini_deep ();
- fontdicts_mod.fini ();
- subset_enc_code_ranges.fini ();
- subset_enc_supp_codes.fini ();
- subset_charset_ranges.fini ();
- sidmap.fini ();
- }
-
- unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+ void 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;
+ unsigned int size0, size1;
+ unsigned code, last_code = CFF_UNDEF_CODE - 1;
hb_vector_t<hb_codepoint_t> supp_codes;
- subset_enc_code_ranges.resize (0);
- supp_size = 0;
+ if (unlikely (!subset_enc_code_ranges.resize (0)))
+ {
+ plan->check_success (false);
+ return;
+ }
+
supp_codes.init ();
+ code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
subset_enc_num_codes = plan->num_output_glyphs () - 1;
unsigned int glyph;
- for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+ auto it = hb_iter (plan->new_to_old_gid_list);
+ if (it->first == 0) it++;
+ auto _ = *it;
+ for (glyph = 1; glyph < num_glyphs; glyph++)
{
- hb_codepoint_t old_glyph;
- if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+ hb_codepoint_t old_glyph;
+ if (glyph == _.first)
{
- /* Retain the code for the old missing glyph ID */
+ old_glyph = _.second;
+ _ = *++it;
+ }
+ else
+ {
+ /* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- code = acc.glyph_to_code (old_glyph);
+ code = acc.glyph_to_code (old_glyph, &glyph_to_sid_cache);
if (code == CFF_UNDEF_CODE)
{
subset_enc_num_codes = glyph - 1;
break;
}
- if ((last_code == CFF_UNDEF_CODE) || (code != last_code + 1))
- {
- code_pair_t pair = { code, glyph };
- subset_enc_code_ranges.push (pair);
- }
+ if (code != last_code + 1)
+ subset_enc_code_ranges.push (code_pair_t {code, glyph});
last_code = code;
- if (encoding != &Null(Encoding))
+ if (encoding != &Null (Encoding))
{
- hb_codepoint_t sid = acc.glyph_to_sid (old_glyph);
+ hb_codepoint_t sid = acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
encoding->get_supplement_codes (sid, supp_codes);
for (unsigned int i = 0; i < supp_codes.length; i++)
- {
- code_pair_t pair = { supp_codes[i], sid };
- subset_enc_supp_codes.push (pair);
- }
- supp_size += SuppEncoding::static_size * supp_codes.length;
+ subset_enc_supp_codes.push (code_pair_t {supp_codes[i], sid});
}
}
supp_codes.fini ();
- subset_enc_code_ranges.finalize (glyph);
+ subset_enc_code_ranges.complete (glyph);
assert (subset_enc_num_codes <= 0xFF);
size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
@@ -525,48 +489,95 @@ struct cff_subset_plan {
subset_enc_format = 0;
else
subset_enc_format = 1;
-
- return Encoding::calculate_serialized_size (
- subset_enc_format,
- subset_enc_format? subset_enc_code_ranges.length: subset_enc_num_codes,
- subset_enc_supp_codes.length);
}
- unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+ bool plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
{
unsigned int size0, size_ranges;
- hb_codepoint_t sid, last_sid = CFF_UNDEF_CODE;
+ unsigned last_sid = CFF_UNDEF_CODE - 1;
- subset_charset_ranges.resize (0);
- unsigned int glyph;
- for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
+ if (unlikely (!subset_charset_ranges.resize (0)))
+ {
+ plan->check_success (false);
+ return false;
+ }
+
+ code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID};
+
+ unsigned num_glyphs = plan->num_output_glyphs ();
+
+ if (unlikely (!subset_charset_ranges.alloc (hb_min (num_glyphs,
+ acc.num_charset_entries))))
+ {
+ plan->check_success (false);
+ return false;
+ }
+
+ glyph_to_sid_map_t *glyph_to_sid_map = acc.cff_accelerator ?
+ acc.cff_accelerator->glyph_to_sid_map.get_acquire () :
+ nullptr;
+ bool created_map = false;
+ if (!glyph_to_sid_map && acc.cff_accelerator)
+ {
+ created_map = true;
+ glyph_to_sid_map = acc.create_glyph_to_sid_map ();
+ }
+
+ auto it = hb_iter (plan->new_to_old_gid_list);
+ if (it->first == 0) it++;
+ auto _ = *it;
+ bool not_is_cid = !acc.is_CID ();
+ bool skip = !not_is_cid && glyph_to_sid_map;
+ if (not_is_cid)
+ sidmap.alloc (num_glyphs);
+ for (hb_codepoint_t glyph = 1; glyph < num_glyphs; glyph++)
{
- hb_codepoint_t old_glyph;
- if (!plan->old_gid_for_new_gid (glyph, &old_glyph))
+ hb_codepoint_t old_glyph;
+ if (glyph == _.first)
{
- /* Retain the SID for the old missing glyph ID */
+ old_glyph = _.second;
+ _ = *++it;
+ }
+ else
+ {
+ /* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- sid = acc.glyph_to_sid (old_glyph);
+ unsigned sid = glyph_to_sid_map ?
+ glyph_to_sid_map->arrayZ[old_glyph].code :
+ acc.glyph_to_sid (old_glyph, &glyph_to_sid_cache);
- if (!acc.is_CID ())
+ if (not_is_cid)
sid = sidmap.add (sid);
- if ((last_sid == CFF_UNDEF_CODE) || (sid != last_sid + 1))
+ if (sid != last_sid + 1)
+ subset_charset_ranges.push (code_pair_t {sid, glyph});
+
+ if (glyph == old_glyph && skip)
{
- code_pair_t pair = { sid, glyph };
- subset_charset_ranges.push (pair);
+ glyph = hb_min (_.first - 1, glyph_to_sid_map->arrayZ[old_glyph].glyph);
+ sid += glyph - old_glyph;
}
last_sid = sid;
}
- bool two_byte = subset_charset_ranges.finalize (glyph);
+ if (created_map)
+ {
+ if ((!plan->accelerator && acc.cff_accelerator) ||
+ !acc.cff_accelerator->glyph_to_sid_map.cmpexch (nullptr, glyph_to_sid_map))
+ {
+ glyph_to_sid_map->~glyph_to_sid_map_t ();
+ hb_free (glyph_to_sid_map);
+ }
+ }
- size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
+ bool two_byte = subset_charset_ranges.complete (num_glyphs);
+
+ size0 = Charset0::get_size (plan->num_output_glyphs ());
if (!two_byte)
- size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+ size_ranges = Charset1::get_size_for_ranges (subset_charset_ranges.length);
else
- size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+ size_ranges = Charset2::get_size_for_ranges (subset_charset_ranges.length);
if (size0 < size_ranges)
subset_charset_format = 0;
@@ -575,26 +586,21 @@ struct cff_subset_plan {
else
subset_charset_format = 2;
- return Charset::calculate_serialized_size (
- subset_charset_format,
- subset_charset_format? subset_charset_ranges.length: plan->num_output_glyphs ());
+ return true;
}
bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
{
- sidmap.reset ();
-
for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
{
unsigned int sid = acc.topDict.nameSIDs[i];
if (sid != CFF_UNDEF_SID)
{
- (void)sidmap.add (sid);
- topDictModSIDs[i] = sidmap[sid];
+ topDictModSIDs[i] = sidmap.add (sid);
}
}
- if (acc.fdArray != &Null(CFF1FDArray))
+ if (acc.fdArray != &Null (CFF1FDArray))
for (unsigned int i = 0; i < orig_fdcount; i++)
if (fdmap.has (i))
(void)sidmap.add (acc.fontDicts[i].fontName);
@@ -609,34 +615,31 @@ struct cff_subset_plan {
hb_codepoint_t old_glyph;
if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false;
- final_size = 0;
num_glyphs = plan->num_output_glyphs ();
orig_fdcount = acc.fdCount;
- drop_hints = plan->drop_hints;
- desubroutinize = plan->desubroutinize;
-
- /* check whether the subset renumbers any glyph IDs */
- gid_renum = false;
- for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++)
- {
- if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph))
- continue;
- if (new_glyph != old_glyph) {
- gid_renum = true;
- break;
+ drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
+ desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
+
+ #ifdef HB_EXPERIMENTAL_API
+ min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
+ #else
+ min_charstrings_off_size = 0;
+ #endif
+
+ subset_charset = !acc.is_predef_charset ();
+ if (!subset_charset)
+ /* check whether the subset renumbers any glyph IDs */
+ for (const auto &_ : plan->new_to_old_gid_list)
+ {
+ if (_.first != _.second)
+ {
+ subset_charset = true;
+ break;
+ }
}
- }
- subset_charset = gid_renum || !acc.is_predef_charset ();
subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
- /* CFF header */
- final_size += OT::cff1::static_size;
-
- /* Name INDEX */
- offsets.nameIndexOffset = final_size;
- final_size += acc.nameIndex->get_size ();
-
/* top dict INDEX */
{
/* Add encoding/charset to a (copy of) top dict as necessary */
@@ -650,25 +653,16 @@ struct cff_subset_plan {
if (need_to_add_set)
topdict_mod.add_op (OpCode_charset);
}
- offsets.topDictInfo.offset = final_size;
- cff1_top_dict_op_serializer_t topSzr;
- unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
- offsets.topDictInfo.offSize = calcOffSize(topDictSize);
- if (unlikely (offsets.topDictInfo.offSize > 4))
- return false;
- final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<cff1_top_dict_values_mod_t>
- (offsets.topDictInfo.offSize,
- &topdict_mod, 1, topdict_sizes, topSzr);
}
/* Determine re-mapping of font index as fdmap among other info */
- if (acc.fdSelect != &Null(CFF1FDSelect))
+ if (acc.fdSelect != &Null (CFF1FDSelect))
{
if (unlikely (!hb_plan_subset_cff_fdselect (plan,
orig_fdcount,
*acc.fdSelect,
subset_fdcount,
- offsets.FDSelectInfo.size,
+ info.fd_select.size,
subset_fdselect_format,
subset_fdselect_ranges,
fdmap)))
@@ -683,18 +677,12 @@ struct cff_subset_plan {
if (unlikely (!collect_sids_in_dicts (acc)))
return false;
if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */
- return false;
- if (subset_charset)
- offsets.charsetInfo.size = plan_subset_charset (acc, plan);
+ return false;
- topdict_mod.reassignSIDs (sidmap);
- }
+ if (subset_charset && !plan_subset_charset (acc, plan))
+ return false;
- /* String INDEX */
- {
- offsets.stringIndexInfo.offset = final_size;
- offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
- final_size += offsets.stringIndexInfo.size;
+ topdict_mod.reassignSIDs (sidmap);
}
if (desubroutinize)
@@ -704,9 +692,6 @@ struct cff_subset_plan {
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
-
- /* no global/local subroutines */
- offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (1, 0, 0);
}
else
{
@@ -723,136 +708,54 @@ struct cff_subset_plan {
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
return false;
- /* global subrs */
- unsigned int dataSize = subset_globalsubrs.total_size ();
- offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
- if (unlikely (offsets.globalSubrsInfo.offSize > 4))
- return false;
- offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
-
/* local subrs */
- if (!offsets.localSubrsInfos.resize (orig_fdcount))
- return false;
if (!subset_localsubrs.resize (orig_fdcount))
return false;
for (unsigned int fd = 0; fd < orig_fdcount; fd++)
{
subset_localsubrs[fd].init ();
- offsets.localSubrsInfos[fd].init ();
if (fdmap.has (fd))
{
if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
return false;
-
- unsigned int dataSize = subset_localsubrs[fd].total_size ();
- if (dataSize > 0)
- {
- offsets.localSubrsInfos[fd].offset = final_size;
- offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
- if (unlikely (offsets.localSubrsInfos[fd].offSize > 4))
- return false;
- offsets.localSubrsInfos[fd].size = CFF1Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
- }
}
}
}
- /* global subrs */
- offsets.globalSubrsInfo.offset = final_size;
- final_size += offsets.globalSubrsInfo.size;
-
/* Encoding */
- if (!subset_encoding)
- offsets.encodingOffset = acc.topDict.EncodingOffset;
- else
- {
- offsets.encodingOffset = final_size;
- final_size += plan_subset_encoding (acc, plan);
- }
-
- /* Charset */
- if (!subset_charset && acc.is_predef_charset ())
- offsets.charsetInfo.offset = acc.topDict.CharsetOffset;
- else
- offsets.charsetInfo.offset = final_size;
- final_size += offsets.charsetInfo.size;
-
- /* FDSelect */
- if (acc.fdSelect != &Null(CFF1FDSelect))
- {
- offsets.FDSelectInfo.offset = final_size;
- final_size += offsets.FDSelectInfo.size;
- }
-
- /* FDArray (FDIndex) */
- if (acc.fdArray != &Null(CFF1FDArray)) {
- offsets.FDArrayInfo.offset = final_size;
- cff1_font_dict_op_serializer_t fontSzr;
- unsigned int dictsSize = 0;
- for (unsigned int i = 0; i < acc.fontDicts.length; i++)
- if (fdmap.has (i))
- dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
-
- offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
- if (unlikely (offsets.FDArrayInfo.offSize > 4))
- return false;
- final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
- }
-
- /* CharStrings */
- {
- offsets.charStringsInfo.offset = final_size;
- unsigned int dataSize = subset_charstrings.total_size ();
- offsets.charStringsInfo.offSize = calcOffSize (dataSize);
- if (unlikely (offsets.charStringsInfo.offSize > 4))
- return false;
- final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
- }
+ if (subset_encoding)
+ plan_subset_encoding (acc, plan);
/* private dicts & local subrs */
- offsets.privateDictInfo.offset = final_size;
- for (unsigned int i = 0; i < orig_fdcount; i++)
+ if (!acc.is_CID ())
+ fontdicts_mod.push (cff1_font_dict_values_mod_t ());
+ else
{
- if (fdmap.has (i))
- {
- bool has_localsubrs = offsets.localSubrsInfos[i].size > 0;
- cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
- unsigned int priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
- table_info_t privInfo = { final_size, priv_size, 0 };
- font_dict_values_mod_t fontdict_mod;
- if (!acc.is_CID ())
- fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
- else
- fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
- fontdicts_mod.push (fontdict_mod);
- final_size += privInfo.size;
-
- if (!plan->desubroutinize && has_localsubrs)
+ + hb_iter (acc.fontDicts)
+ | hb_filter ([&] (const cff1_font_dict_values_t &_)
+ { return fdmap.has (&_ - &acc.fontDicts[0]); } )
+ | hb_map ([&] (const cff1_font_dict_values_t &_)
{
- offsets.localSubrsInfos[i].offset = final_size;
- final_size += offsets.localSubrsInfos[i].size;
- }
- }
+ cff1_font_dict_values_mod_t mod;
+ mod.init (&_, sidmap[_.fontName]);
+ return mod;
+ })
+ | hb_sink (fontdicts_mod)
+ ;
}
- if (!acc.is_CID ())
- offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
-
- return ((subset_charstrings.length == plan->num_output_glyphs ())
- && (fontdicts_mod.length == subset_fdcount));
+ return !plan->in_error () &&
+ (subset_charstrings.length == plan->num_output_glyphs ()) &&
+ (fontdicts_mod.length == subset_fdcount);
}
- unsigned int get_final_size () const { return final_size; }
-
- unsigned int final_size;
- hb_vector_t<unsigned int> topdict_sizes;
cff1_top_dict_values_mod_t topdict_mod;
- cff1_sub_table_offsets_t offsets;
+ cff1_sub_table_info_t info;
unsigned int num_glyphs;
- unsigned int orig_fdcount;
- unsigned int subset_fdcount;
- unsigned int subset_fdselect_format;
+ unsigned int orig_fdcount = 0;
+ unsigned int subset_fdcount = 1;
+ unsigned int subset_fdselect_format = 0;
hb_vector_t<code_pair_t> subset_fdselect_ranges;
/* font dict index remap table from fullset FDArray to subset FDArray.
@@ -862,9 +765,9 @@ struct cff_subset_plan {
str_buff_vec_t subset_charstrings;
str_buff_vec_t subset_globalsubrs;
hb_vector_t<str_buff_vec_t> subset_localsubrs;
- hb_vector_t<font_dict_values_mod_t> fontdicts_mod;
+ hb_vector_t<cff1_font_dict_values_mod_t> fontdicts_mod;
- bool drop_hints;
+ bool drop_hints = false;
bool gid_renum;
bool subset_encoding;
@@ -880,77 +783,124 @@ struct cff_subset_plan {
remap_sid_t sidmap;
unsigned int topDictModSIDs[name_dict_values_t::ValCount];
- bool desubroutinize;
+ bool desubroutinize = false;
+
+ unsigned min_charstrings_off_size = 0;
};
+} // namespace OT
-static inline bool _write_cff1 (const cff_subset_plan &plan,
- const OT::cff1::accelerator_subset_t &acc,
- unsigned int num_glyphs,
- unsigned int dest_sz,
- void *dest)
+static bool _serialize_cff1_charstrings (hb_serialize_context_t *c,
+ struct OT::cff1_subset_plan &plan,
+ const OT::cff1::accelerator_subset_t &acc)
{
- hb_serialize_context_t c (dest, dest_sz);
+ c->push<CFF1CharStrings> ();
- OT::cff1 *cff = c.start_serialize<OT::cff1> ();
- if (unlikely (!c.extend_min (*cff)))
+ unsigned data_size = 0;
+ unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
+ if (unlikely (!c->start_zerocopy (total_size)))
return false;
- /* header */
- cff->version.major = 0x01;
- cff->version.minor = 0x00;
- cff->nameIndex = cff->min_size;
- cff->offSize = 4; /* unused? */
+ auto *cs = c->start_embed<CFF1CharStrings> ();
+ if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size))) {
+ c->pop_discard ();
+ return false;
+ }
- /* name INDEX */
+ plan.info.char_strings_link = c->pop_pack (false);
+ return true;
+}
+
+bool
+OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+ struct OT::cff1_subset_plan &plan) const
+{
+ /* push charstrings onto the object stack first which will ensure it packs as the last
+ object in the table. Keeping the chastrings last satisfies the requirements for patching
+ via IFTB. If this ordering needs to be changed in the future, charstrings should be left
+ at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
+ if (!_serialize_cff1_charstrings(c, plan, *this))
+ return false;
+
+ /* private dicts & local subrs */
+ for (int i = (int) privateDicts.length; --i >= 0 ;)
{
- assert (cff->nameIndex == (unsigned) (c.head - c.start));
- CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
+ if (plan.fdmap.has (i))
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
- return false;
+ objidx_t subrs_link = 0;
+ if (plan.subset_localsubrs[i].length > 0)
+ {
+ auto *dest = c->push <CFF1Subrs> ();
+ if (likely (dest->serialize (c, plan.subset_localsubrs[i])))
+ subrs_link = c->pop_pack ();
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+
+ auto *pd = c->push<PrivateDict> ();
+ cff1_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+ if (likely (pd->serialize (c, privateDicts[i], privSzr, subrs_link)))
+ {
+ unsigned fd = plan.fdmap[i];
+ plan.fontdicts_mod[fd].privateDictInfo.size = c->length ();
+ plan.fontdicts_mod[fd].privateDictInfo.link = c->pop_pack ();
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
}
}
- /* top dict INDEX */
+ if (!is_CID ())
+ plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
+
+ /* FDArray (FD Index) */
+ if (fdArray != &Null (CFF1FDArray))
{
- assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
- CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict>> ();
- if (dest == nullptr) return false;
- cff1_top_dict_op_serializer_t topSzr;
- top_dict_modifiers_t modifier (plan.offsets, plan.topDictModSIDs);
- if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
- &plan.topdict_mod, 1,
- plan.topdict_sizes, topSzr, modifier)))
+ auto *fda = c->push<CFF1FDArray> ();
+ cff1_font_dict_op_serializer_t fontSzr;
+ auto it = + hb_zip (+ hb_iter (plan.fontdicts_mod), + hb_iter (plan.fontdicts_mod));
+ if (likely (fda->serialize (c, it, fontSzr)))
+ plan.info.fd_array_link = c->pop_pack (false);
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
+ c->pop_discard ();
return false;
}
}
- /* String INDEX */
+ /* FDSelect */
+ if (fdSelect != &Null (CFF1FDSelect))
{
- assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start));
- CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
+ c->push ();
+ if (likely (hb_serialize_cff_fdselect (c, plan.num_glyphs, *fdSelect, fdCount,
+ plan.subset_fdselect_format, plan.info.fd_select.size,
+ plan.subset_fdselect_ranges)))
+ plan.info.fd_select.link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
+ c->pop_discard ();
return false;
}
}
- /* global subrs */
+ /* Charset */
+ if (plan.subset_charset)
{
- assert (plan.offsets.globalSubrsInfo.offset != 0);
- assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start));
-
- CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+ auto *dest = c->push<Charset> ();
+ if (likely (dest->serialize (c,
+ plan.subset_charset_format,
+ plan.num_glyphs,
+ plan.subset_charset_ranges)))
+ plan.info.charset_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+ c->pop_discard ();
return false;
}
}
@@ -958,169 +908,93 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* Encoding */
if (plan.subset_encoding)
{
- assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start));
- Encoding *dest = c.start_embed<Encoding> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c,
- plan.subset_enc_format,
- plan.subset_enc_num_codes,
- plan.subset_enc_code_ranges,
- plan.subset_enc_supp_codes)))
+ auto *dest = c->push<Encoding> ();
+ if (likely (dest->serialize (c,
+ plan.subset_enc_format,
+ plan.subset_enc_num_codes,
+ plan.subset_enc_code_ranges,
+ plan.subset_enc_supp_codes)))
+ plan.info.encoding_link = c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
+ c->pop_discard ();
return false;
}
}
- /* Charset */
- if (plan.subset_charset)
+ /* global subrs */
{
- assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start));
- Charset *dest = c.start_embed<Charset> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c,
- plan.subset_charset_format,
- plan.num_glyphs,
- plan.subset_charset_ranges)))
+ auto *dest = c->push <CFF1Subrs> ();
+ if (likely (dest->serialize (c, plan.subset_globalsubrs)))
+ c->pop_pack (false);
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
+ c->pop_discard ();
return false;
}
}
- /* FDSelect */
- if (acc.fdSelect != &Null(CFF1FDSelect))
+ /* String INDEX */
{
- assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
-
- if (unlikely (!hb_serialize_cff_fdselect (&c, num_glyphs, *acc.fdSelect, acc.fdCount,
- plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
- plan.subset_fdselect_ranges)))
+ auto *dest = c->push<CFF1StringIndex> ();
+ if (likely (!plan.sidmap.in_error () &&
+ dest->serialize (c, *stringIndex, plan.sidmap.vector)))
+ c->pop_pack ();
+ else
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
+ c->pop_discard ();
return false;
}
}
- /* FDArray (FD Index) */
- if (acc.fdArray != &Null(CFF1FDArray))
- {
- assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
- CFF1FDArray *fda = c.start_embed<CFF1FDArray> ();
- if (unlikely (fda == nullptr)) return false;
- cff1_font_dict_op_serializer_t fontSzr;
- if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
- plan.fontdicts_mod,
- fontSzr)))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
- return false;
- }
- }
+ OT::cff1 *cff = c->allocate_min<OT::cff1> ();
+ if (unlikely (!cff))
+ return false;
+
+ /* header */
+ cff->version.major = 0x01;
+ cff->version.minor = 0x00;
+ cff->nameIndex = cff->min_size;
+ cff->offSize = 4; /* unused? */
- /* CharStrings */
+ /* name INDEX */
+ if (unlikely (!c->embed (*nameIndex))) return false;
+
+ /* top dict INDEX */
{
- assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
- CFF1CharStrings *cs = c.start_embed<CFF1CharStrings> ();
- if (unlikely (cs == nullptr)) return false;
- if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+ /* serialize singleton TopDict */
+ auto *top = c->push<TopDict> ();
+ cff1_top_dict_op_serializer_t topSzr;
+ unsigned top_size = 0;
+ top_dict_modifiers_t modifier (plan.info, plan.topDictModSIDs);
+ if (likely (top->serialize (c, plan.topdict_mod, topSzr, modifier)))
{
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
- return false;
+ top_size = c->length ();
+ c->pop_pack (false);
}
- }
-
- /* private dicts & local subrs */
- assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
- for (unsigned int i = 0; i < acc.privateDicts.length; i++)
- {
- if (plan.fdmap.has (i))
+ else
{
- PrivateDict *pd = c.start_embed<PrivateDict> ();
- if (unlikely (pd == nullptr)) return false;
- unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
- bool result;
- cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
- /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
- unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
- result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
- if (unlikely (!result))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
- return false;
- }
- if (plan.offsets.localSubrsInfos[i].size > 0)
- {
- CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
- if (unlikely (dest == nullptr)) return false;
- if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
- {
- DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
- return false;
- }
- }
+ c->pop_discard ();
+ return false;
}
+ /* serialize INDEX header for above */
+ auto *dest = c->start_embed<CFF1Index> ();
+ return dest->serialize_header (c, hb_iter (&top_size, 1), top_size);
}
-
- assert (c.head == c.end);
- c.end_serialize ();
-
- return true;
}
-static inline bool
-_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
- const char *data,
- hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
+bool
+OT::cff1::accelerator_subset_t::subset (hb_subset_context_t *c) const
{
- cff_subset_plan cff_plan;
+ cff1_subset_plan cff_plan;
- if (unlikely (!cff_plan.create (acc, plan)))
+ if (unlikely (!cff_plan.create (*this, c->plan)))
{
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
return false;
}
- unsigned int cff_prime_size = cff_plan.get_final_size ();
- char *cff_prime_data = (char *) calloc (1, cff_prime_size);
-
- if (unlikely (!_write_cff1 (cff_plan, acc, plan->num_output_glyphs (),
- cff_prime_size, cff_prime_data))) {
- DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
- free (cff_prime_data);
- return false;
- }
-
- *prime = hb_blob_create (cff_prime_data,
- cff_prime_size,
- HB_MEMORY_MODE_READONLY,
- cff_prime_data,
- free);
- return true;
-}
-
-/**
- * hb_subset_cff1:
- * Subsets the CFF table according to a provided plan.
- *
- * Return value: subsetted cff table.
- **/
-bool
-hb_subset_cff1 (hb_subset_plan_t *plan,
- hb_blob_t **prime /* OUT */)
-{
- hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source);
- const char *data = hb_blob_get_data(cff_blob, nullptr);
-
- OT::cff1::accelerator_subset_t acc;
- acc.init(plan->source);
- bool result = likely (acc.is_valid ()) &&
- _hb_subset_cff1 (acc, data, plan, prime);
- hb_blob_destroy (cff_blob);
- acc.fini ();
-
- return result;
+ return serialize (c->serializer, cff_plan);
}