[subset-cff] Optimize op_str_t layout

This commit is contained in:
Behdad Esfahbod 2022-11-21 21:37:38 -07:00
parent a750cb0128
commit 4f056b923a
3 changed files with 26 additions and 17 deletions

View File

@ -480,7 +480,11 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
hb_ubytes_t str;
/* This used to be a hb_ubytes_t. Using a pointer and length
* saves 8 bytes in the struct. */
const unsigned char *ptr = nullptr;
unsigned length = 0;
op_code_t op;
};
@ -492,9 +496,9 @@ struct op_serializer_t
{
TRACE_SERIALIZE (this);
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.length);
if (unlikely (!d)) return_trace (false);
memcpy (d, &opstr.str[0], opstr.str.length);
memcpy (d, opstr.ptr, opstr.length);
return_trace (true);
}
};
@ -518,7 +522,9 @@ struct parsed_values_t
{
VAL *val = values.push ();
val->op = op;
val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
val->ptr = arr.arrayZ;
val->length = arr.length;
opStart = str_ref.get_offset ();
}
@ -526,7 +532,9 @@ struct parsed_values_t
{
VAL *val = values.push (v);
val->op = op;
val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
val->ptr = arr.arrayZ;
val->length = arr.length;
opStart = str_ref.get_offset ();
}

View File

@ -104,20 +104,20 @@ struct str_encoder_t
encode_byte (op);
}
void copy_str (const hb_ubytes_t &str)
void copy_str (const unsigned char *str, unsigned length)
{
unsigned int offset = buff.length;
/* Manually resize buffer since faster. */
if (likely ((signed) (buff.length + str.length) <= buff.allocated))
buff.length += str.length;
else if (unlikely (!buff.resize (offset + str.length)))
if (likely ((signed) (buff.length + length) <= buff.allocated))
buff.length += length;
else if (unlikely (!buff.resize (offset + length)))
return;
/* Since our strings are one or two bytes typically,
* this is faster than memcpy. */
for (unsigned i = 0; i < str.length; i++)
buff.arrayZ[i + offset] = str.arrayZ[i];
// memcpy (buff.arrayZ + offset, &str[0], str.length);
for (unsigned i = 0; i < length; i++)
buff.arrayZ[i + offset] = str[i];
// memcpy (buff.arrayZ + offset, str, length);
}
bool is_error () const { return buff.in_error (); }
@ -183,9 +183,9 @@ struct cff_font_dict_op_serializer_t : op_serializer_t
}
else
{
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.length);
if (unlikely (!d)) return_trace (false);
memcpy (d, &opstr.str[0], opstr.str.length);
memcpy (d, opstr.ptr, opstr.length);
}
return_trace (true);
}
@ -883,7 +883,7 @@ struct subr_subsetter_t
break;
default:
encoder.copy_str (opstr.str);
encoder.copy_str (opstr.ptr, opstr.length);
break;
}
}

View File

@ -167,9 +167,10 @@ 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 = hb_ubytes_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));