Merge branch 'master' into iter
This commit is contained in:
commit
cbe2118c58
7
NEWS
7
NEWS
|
@ -1,3 +1,10 @@
|
|||
Overview of changes leading to 2.3.1
|
||||
Wednesday, January 30, 2019
|
||||
====================================
|
||||
- AAT bug fixes.
|
||||
- Misc internal housekeeping cleanup.
|
||||
|
||||
|
||||
Overview of changes leading to 2.3.0
|
||||
Thursday, December 20, 2018
|
||||
====================================
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[2.3.0],
|
||||
[2.3.1],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
|
|
@ -57,16 +57,19 @@ struct DeviceRecord
|
|||
}
|
||||
|
||||
unsigned int len () const
|
||||
{ return this->subset_plan->glyphs.length; }
|
||||
{ return this->subset_plan->num_output_glyphs (); }
|
||||
|
||||
const HBUINT8* operator [] (unsigned int i) const
|
||||
const HBUINT8* operator [] (unsigned int new_gid) const
|
||||
{
|
||||
if (unlikely (i >= len ())) return nullptr;
|
||||
hb_codepoint_t gid = this->subset_plan->glyphs [i];
|
||||
if (unlikely (new_gid >= len ())) return nullptr;
|
||||
|
||||
if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
|
||||
hb_codepoint_t old_gid;
|
||||
if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
|
||||
return &Null(HBUINT8);
|
||||
|
||||
if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
|
||||
return nullptr;
|
||||
return &(this->source_device_record->widthsZ[gid]);
|
||||
return &(this->source_device_record->widthsZ[old_gid]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,7 +143,7 @@ struct hdmx
|
|||
|
||||
this->version.set (source_hdmx->version);
|
||||
this->numRecords.set (source_hdmx->numRecords);
|
||||
this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
|
||||
this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->num_output_glyphs ()));
|
||||
|
||||
for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
|
||||
{
|
||||
|
@ -156,7 +159,7 @@ struct hdmx
|
|||
|
||||
static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
|
||||
{
|
||||
return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
|
||||
return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_output_glyphs ());
|
||||
}
|
||||
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
|
|
|
@ -66,7 +66,7 @@ struct hmtxvmtx
|
|||
|
||||
|
||||
bool subset_update_header (hb_subset_plan_t *plan,
|
||||
unsigned int num_hmetrics) const
|
||||
unsigned int num_hmetrics) const
|
||||
{
|
||||
hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
|
||||
hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
|
||||
|
@ -93,75 +93,49 @@ struct hmtxvmtx
|
|||
|
||||
/* All the trailing glyphs with the same advance can use one LongMetric
|
||||
* and just keep LSB */
|
||||
hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
|
||||
unsigned int num_advances = gids.length;
|
||||
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
|
||||
while (num_advances > 1 &&
|
||||
last_advance == _mtx.get_advance (gids[num_advances - 2]))
|
||||
{
|
||||
num_advances--;
|
||||
}
|
||||
unsigned int num_output_glyphs = plan->num_output_glyphs ();
|
||||
unsigned int num_advances = _mtx.num_advances_for_subset (plan);
|
||||
|
||||
/* alloc the new table */
|
||||
size_t dest_sz = num_advances * 4
|
||||
+ (gids.length - num_advances) * 2;
|
||||
+ (num_output_glyphs - num_advances) * 2;
|
||||
void *dest = (void *) malloc (dest_sz);
|
||||
if (unlikely (!dest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
|
||||
DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz);
|
||||
DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes",
|
||||
HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz);
|
||||
|
||||
const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
|
||||
// Copy everything over
|
||||
LongMetric * old_metrics = (LongMetric *) source_table;
|
||||
FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
|
||||
char * dest_pos = (char *) dest;
|
||||
|
||||
bool failed = false;
|
||||
for (unsigned int i = 0; i < gids.length; i++)
|
||||
for (unsigned int i = 0; i < num_output_glyphs; i++)
|
||||
{
|
||||
/* the last metric or the one for gids[i] */
|
||||
LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
|
||||
if (gids[i] < _mtx.num_advances)
|
||||
unsigned int side_bearing = 0;
|
||||
unsigned int advance = 0;
|
||||
hb_codepoint_t old_gid;
|
||||
if (plan->old_gid_for_new_gid (i, &old_gid))
|
||||
{
|
||||
/* src is a LongMetric */
|
||||
if (i < num_advances)
|
||||
{
|
||||
/* dest is a LongMetric, copy it */
|
||||
*((LongMetric *) dest_pos) = *src_metric;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dest just sb */
|
||||
*((FWORD *) dest_pos) = src_metric->sb;
|
||||
}
|
||||
// Glyph is not an empty glyph so copy advance and side bearing
|
||||
// from the input font.
|
||||
side_bearing = _mtx.get_side_bearing (old_gid);
|
||||
advance = _mtx.get_advance (old_gid);
|
||||
}
|
||||
|
||||
bool has_advance = i < num_advances;
|
||||
if (has_advance)
|
||||
{
|
||||
((LongMetric *) dest_pos)->advance.set (advance);
|
||||
((LongMetric *) dest_pos)->sb.set (side_bearing);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gids[i] >= _mtx.num_metrics)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
|
||||
gids[i], _mtx.num_metrics);
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
|
||||
if (i < num_advances)
|
||||
{
|
||||
/* dest needs a full LongMetric */
|
||||
LongMetric *metric = (LongMetric *)dest_pos;
|
||||
metric->advance = src_metric->advance;
|
||||
metric->sb = src_sb;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dest just needs an sb */
|
||||
*((FWORD *) dest_pos) = src_sb;
|
||||
}
|
||||
((FWORD *) dest_pos)->set (side_bearing);
|
||||
}
|
||||
dest_pos += (i < num_advances ? 4 : 2);
|
||||
dest_pos += (has_advance ? 4 : 2);
|
||||
}
|
||||
_mtx.fini ();
|
||||
|
||||
|
@ -187,7 +161,7 @@ struct hmtxvmtx
|
|||
friend struct hmtxvmtx;
|
||||
|
||||
void init (hb_face_t *face,
|
||||
unsigned int default_advance_ = 0)
|
||||
unsigned int default_advance_ = 0)
|
||||
{
|
||||
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
|
||||
|
||||
|
@ -280,6 +254,32 @@ struct hmtxvmtx
|
|||
return advance;
|
||||
}
|
||||
|
||||
unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const
|
||||
{
|
||||
unsigned int num_advances = plan->num_output_glyphs ();
|
||||
unsigned int last_advance = _advance_for_new_gid (plan,
|
||||
num_advances - 1);
|
||||
while (num_advances > 1 &&
|
||||
last_advance == _advance_for_new_gid (plan,
|
||||
num_advances - 2))
|
||||
{
|
||||
num_advances--;
|
||||
}
|
||||
|
||||
return num_advances;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
|
||||
hb_codepoint_t new_gid) const
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
|
||||
return 0;
|
||||
|
||||
return get_advance (old_gid);
|
||||
}
|
||||
|
||||
public:
|
||||
bool has_font_extents;
|
||||
int ascender;
|
||||
|
|
|
@ -1233,7 +1233,7 @@ struct ClassDefFormat1
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset;
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
hb_sorted_vector_t<GlyphID> glyphs;
|
||||
hb_vector_t<HBUINT16> klasses;
|
||||
|
@ -1380,7 +1380,7 @@ struct ClassDefFormat2
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset;
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
hb_vector_t<GlyphID> glyphs;
|
||||
hb_vector_t<HBUINT16> klasses;
|
||||
|
|
|
@ -95,7 +95,7 @@ struct SingleSubstFormat1
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset;
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
hb_sorted_vector_t<GlyphID> from;
|
||||
hb_vector_t<GlyphID> to;
|
||||
|
@ -184,7 +184,7 @@ struct SingleSubstFormat2
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset;
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
hb_sorted_vector_t<GlyphID> from;
|
||||
hb_vector_t<GlyphID> to;
|
||||
|
|
|
@ -105,7 +105,7 @@ struct maxp
|
|||
}
|
||||
maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
|
||||
|
||||
maxp_prime->set_num_glyphs (plan->glyphs.length);
|
||||
maxp_prime->set_num_glyphs (plan->num_output_glyphs ());
|
||||
if (plan->drop_hints)
|
||||
drop_hint_fields (plan, maxp_prime);
|
||||
|
||||
|
|
|
@ -110,21 +110,29 @@ struct VORG
|
|||
/* count the number of glyphs to be included in the subset table */
|
||||
hb_vector_t<VertOriginMetric> subset_metrics;
|
||||
subset_metrics.init ();
|
||||
unsigned int glyph = 0;
|
||||
|
||||
|
||||
hb_codepoint_t old_glyph = HB_SET_VALUE_INVALID;
|
||||
unsigned int i = 0;
|
||||
while ((glyph < plan->glyphs.length) && (i < vertYOrigins.len))
|
||||
while (i < vertYOrigins.len
|
||||
&& plan->glyphset ()->next (&old_glyph))
|
||||
{
|
||||
if (plan->glyphs[glyph] > vertYOrigins[i].glyph)
|
||||
i++;
|
||||
else if (plan->glyphs[glyph] < vertYOrigins[i].glyph)
|
||||
glyph++;
|
||||
else
|
||||
while (old_glyph > vertYOrigins[i].glyph)
|
||||
{
|
||||
VertOriginMetric *metrics = subset_metrics.push ();
|
||||
metrics->glyph.set (glyph);
|
||||
metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
|
||||
glyph++;
|
||||
i++;
|
||||
if (i >= vertYOrigins.len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (old_glyph == vertYOrigins[i].glyph)
|
||||
{
|
||||
hb_codepoint_t new_glyph;
|
||||
if (plan->new_gid_for_old_gid (old_glyph, &new_glyph))
|
||||
{
|
||||
VertOriginMetric *metrics = subset_metrics.push ();
|
||||
metrics->glyph.set (new_glyph);
|
||||
metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -469,11 +469,11 @@ struct cff_subset_plan {
|
|||
supp_size = 0;
|
||||
supp_codes.init ();
|
||||
|
||||
subset_enc_num_codes = plan->glyphs.length - 1;
|
||||
subset_enc_num_codes = plan->glyphs_deprecated.length - 1;
|
||||
unsigned int glyph;
|
||||
for (glyph = 1; glyph < plan->glyphs.length; glyph++)
|
||||
for (glyph = 1; glyph < plan->glyphs_deprecated.length; glyph++)
|
||||
{
|
||||
hb_codepoint_t orig_glyph = plan->glyphs[glyph];
|
||||
hb_codepoint_t orig_glyph = plan->glyphs_deprecated[glyph];
|
||||
code = acc.glyph_to_code (orig_glyph);
|
||||
if (code == CFF_UNDEF_CODE)
|
||||
{
|
||||
|
@ -526,9 +526,9 @@ struct cff_subset_plan {
|
|||
|
||||
subset_charset_ranges.resize (0);
|
||||
unsigned int glyph;
|
||||
for (glyph = 1; glyph < plan->glyphs.length; glyph++)
|
||||
for (glyph = 1; glyph < plan->glyphs_deprecated.length; glyph++)
|
||||
{
|
||||
hb_codepoint_t orig_glyph = plan->glyphs[glyph];
|
||||
hb_codepoint_t orig_glyph = plan->glyphs_deprecated[glyph];
|
||||
sid = acc.glyph_to_sid (orig_glyph);
|
||||
|
||||
if (!acc.is_CID ())
|
||||
|
@ -544,7 +544,7 @@ struct cff_subset_plan {
|
|||
|
||||
bool two_byte = subset_charset_ranges.finalize (glyph);
|
||||
|
||||
size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs.length - 1);
|
||||
size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs_deprecated.length - 1);
|
||||
if (!two_byte)
|
||||
size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
|
||||
else
|
||||
|
@ -559,7 +559,7 @@ struct cff_subset_plan {
|
|||
|
||||
return Charset::calculate_serialized_size (
|
||||
subset_charset_format,
|
||||
subset_charset_format? subset_charset_ranges.length: plan->glyphs.length);
|
||||
subset_charset_format? subset_charset_ranges.length: plan->glyphs_deprecated.length);
|
||||
}
|
||||
|
||||
bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
|
||||
|
@ -589,19 +589,19 @@ struct cff_subset_plan {
|
|||
hb_subset_plan_t *plan)
|
||||
{
|
||||
/* make sure notdef is first */
|
||||
if ((plan->glyphs.length == 0) || (plan->glyphs[0] != 0)) return false;
|
||||
if ((plan->glyphs_deprecated.length == 0) || (plan->glyphs_deprecated[0] != 0)) return false;
|
||||
|
||||
final_size = 0;
|
||||
num_glyphs = plan->glyphs.length;
|
||||
num_glyphs = plan->glyphs_deprecated.length;
|
||||
orig_fdcount = acc.fdCount;
|
||||
drop_hints = plan->drop_hints;
|
||||
desubroutinize = plan->desubroutinize;
|
||||
|
||||
/* check whether the subset renumbers any glyph IDs */
|
||||
gid_renum = false;
|
||||
for (unsigned int glyph = 0; glyph < plan->glyphs.length; glyph++)
|
||||
for (unsigned int glyph = 0; glyph < plan->glyphs_deprecated.length; glyph++)
|
||||
{
|
||||
if (plan->glyphs[glyph] != glyph) {
|
||||
if (plan->glyphs_deprecated[glyph] != glyph) {
|
||||
gid_renum = true;
|
||||
break;
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ struct cff_subset_plan {
|
|||
/* Determine re-mapping of font index as fdmap among other info */
|
||||
if (acc.fdSelect != &Null(CFF1FDSelect))
|
||||
{
|
||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs_deprecated,
|
||||
orig_fdcount,
|
||||
*acc.fdSelect,
|
||||
subset_fdcount,
|
||||
|
@ -681,7 +681,7 @@ struct cff_subset_plan {
|
|||
{
|
||||
/* Flatten global & local subrs */
|
||||
subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t>
|
||||
flattener(acc, plan->glyphs, plan->drop_hints);
|
||||
flattener(acc, plan->glyphs_deprecated, plan->drop_hints);
|
||||
if (!flattener.flatten (subset_charstrings))
|
||||
return false;
|
||||
|
||||
|
@ -691,11 +691,11 @@ struct cff_subset_plan {
|
|||
else
|
||||
{
|
||||
/* Subset subrs: collect used subroutines, leaving all unused ones behind */
|
||||
if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
|
||||
if (!subr_subsetter.subset (acc, plan->glyphs_deprecated, plan->drop_hints))
|
||||
return false;
|
||||
|
||||
/* encode charstrings, global subrs, local subrs with new subroutine numbers */
|
||||
if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
|
||||
if (!subr_subsetter.encode_charstrings (acc, plan->glyphs_deprecated, subset_charstrings))
|
||||
return false;
|
||||
|
||||
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
|
||||
|
@ -784,7 +784,7 @@ struct cff_subset_plan {
|
|||
offsets.charStringsInfo.offSize = calcOffSize (dataSize);
|
||||
if (unlikely (offsets.charStringsInfo.offSize > 4))
|
||||
return false;
|
||||
final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
|
||||
final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs_deprecated.length, dataSize);
|
||||
}
|
||||
|
||||
/* private dicts & local subrs */
|
||||
|
@ -816,7 +816,7 @@ struct cff_subset_plan {
|
|||
if (!acc.is_CID ())
|
||||
offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
|
||||
|
||||
return ((subset_charstrings.length == plan->glyphs.length)
|
||||
return ((subset_charstrings.length == plan->glyphs_deprecated.length)
|
||||
&& (fontdicts_mod.length == subset_fdcount));
|
||||
}
|
||||
|
||||
|
@ -1064,7 +1064,7 @@ _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
|
|||
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->glyphs,
|
||||
if (unlikely (!_write_cff1 (cff_plan, acc, plan->glyphs_deprecated,
|
||||
cff_prime_size, cff_prime_data))) {
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
|
||||
free (cff_prime_data);
|
||||
|
|
|
@ -287,7 +287,7 @@ struct cff2_subset_plan {
|
|||
{
|
||||
/* Flatten global & local subrs */
|
||||
subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
|
||||
flattener(acc, plan->glyphs, plan->drop_hints);
|
||||
flattener(acc, plan->glyphs_deprecated, plan->drop_hints);
|
||||
if (!flattener.flatten (subset_charstrings))
|
||||
return false;
|
||||
|
||||
|
@ -297,11 +297,11 @@ struct cff2_subset_plan {
|
|||
else
|
||||
{
|
||||
/* Subset subrs: collect used subroutines, leaving all unused ones behind */
|
||||
if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
|
||||
if (!subr_subsetter.subset (acc, plan->glyphs_deprecated, plan->drop_hints))
|
||||
return false;
|
||||
|
||||
/* encode charstrings, global subrs, local subrs with new subroutine numbers */
|
||||
if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
|
||||
if (!subr_subsetter.encode_charstrings (acc, plan->glyphs_deprecated, subset_charstrings))
|
||||
return false;
|
||||
|
||||
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
|
||||
|
@ -352,7 +352,7 @@ struct cff2_subset_plan {
|
|||
if (acc.fdSelect != &Null(CFF2FDSelect))
|
||||
{
|
||||
offsets.FDSelectInfo.offset = final_size;
|
||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs_deprecated,
|
||||
orig_fdcount,
|
||||
*(const FDSelect *)acc.fdSelect,
|
||||
subset_fdcount,
|
||||
|
@ -385,7 +385,7 @@ struct cff2_subset_plan {
|
|||
offsets.charStringsInfo.offset = final_size;
|
||||
unsigned int dataSize = subset_charstrings.total_size ();
|
||||
offsets.charStringsInfo.offSize = calcOffSize (dataSize);
|
||||
final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
|
||||
final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs_deprecated.length, dataSize);
|
||||
}
|
||||
|
||||
/* private dicts & local subrs */
|
||||
|
@ -584,7 +584,7 @@ _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
|
|||
unsigned int cff2_prime_size = cff2_plan.get_final_size ();
|
||||
char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
|
||||
|
||||
if (unlikely (!_write_cff2 (cff2_plan, acc, plan->glyphs,
|
||||
if (unlikely (!_write_cff2 (cff2_plan, acc, plan->glyphs_deprecated,
|
||||
cff2_prime_size, cff2_prime_data))) {
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
|
||||
free (cff2_prime_data);
|
||||
|
|
|
@ -29,97 +29,128 @@
|
|||
#include "hb-set.h"
|
||||
#include "hb-subset-glyf.hh"
|
||||
|
||||
static bool
|
||||
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
|
||||
hb_vector_t<hb_codepoint_t> &glyph_ids,
|
||||
hb_bool_t drop_hints,
|
||||
bool *use_short_loca /* OUT */,
|
||||
unsigned int *glyf_size /* OUT */,
|
||||
unsigned int *loca_size /* OUT */,
|
||||
hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
|
||||
struct loca_data_t
|
||||
{
|
||||
unsigned int total = 0;
|
||||
for (unsigned int i = 0; i < glyph_ids.length; i++)
|
||||
bool is_short;
|
||||
void *data;
|
||||
unsigned int size;
|
||||
|
||||
inline bool
|
||||
_write_loca_entry (unsigned int id,
|
||||
unsigned int offset)
|
||||
{
|
||||
hb_codepoint_t next_glyph = glyph_ids[i];
|
||||
if (!instruction_ranges->resize (instruction_ranges->length + 2))
|
||||
unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
|
||||
if ((id + 1) * entry_size <= size)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
|
||||
if (is_short) {
|
||||
((OT::HBUINT16*) data) [id].set (offset / 2);
|
||||
} else {
|
||||
((OT::HBUINT32*) data) [id].set (offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Offset was not written because the write is out of bounds.
|
||||
DEBUG_MSG(SUBSET,
|
||||
nullptr,
|
||||
"WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
|
||||
id,
|
||||
size);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If hints are being dropped find the range which in glyf at which
|
||||
* the hinting instructions are located. Add them to the instruction_ranges
|
||||
* vector.
|
||||
*/
|
||||
static bool
|
||||
_add_instructions_range (const OT::glyf::accelerator_t &glyf,
|
||||
hb_codepoint_t glyph_id,
|
||||
unsigned int glyph_start_offset,
|
||||
unsigned int glyph_end_offset,
|
||||
bool drop_hints,
|
||||
hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
|
||||
{
|
||||
if (!instruction_ranges->resize (instruction_ranges->length + 2))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
|
||||
return false;
|
||||
}
|
||||
unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
|
||||
*instruction_start = 0;
|
||||
unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
|
||||
*instruction_end = 0;
|
||||
|
||||
if (drop_hints)
|
||||
{
|
||||
if (unlikely (!glyf.get_instruction_offsets (glyph_start_offset, glyph_end_offset,
|
||||
instruction_start, instruction_end)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", glyph_id);
|
||||
return false;
|
||||
}
|
||||
unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
|
||||
*instruction_start = 0;
|
||||
unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
|
||||
*instruction_end = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
|
||||
const hb_subset_plan_t *plan,
|
||||
loca_data_t *loca_data, /* OUT */
|
||||
unsigned int *glyf_size /* OUT */,
|
||||
hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
|
||||
{
|
||||
unsigned int total = 0;
|
||||
|
||||
hb_codepoint_t next_glyph = HB_SET_VALUE_INVALID;
|
||||
while (plan->glyphset ()->next (&next_glyph))
|
||||
{
|
||||
unsigned int start_offset, end_offset;
|
||||
if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
|
||||
glyf.remove_padding (start_offset, &end_offset))))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
|
||||
continue;
|
||||
start_offset = end_offset = 0;
|
||||
}
|
||||
if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
|
||||
|
||||
bool is_zero_length = end_offset - start_offset < OT::glyf::GlyphHeader::static_size;
|
||||
if (!_add_instructions_range (glyf,
|
||||
next_glyph,
|
||||
start_offset,
|
||||
end_offset,
|
||||
plan->drop_hints && !is_zero_length,
|
||||
instruction_ranges))
|
||||
return false;
|
||||
|
||||
if (is_zero_length)
|
||||
continue; /* 0-length glyph */
|
||||
|
||||
if (drop_hints)
|
||||
{
|
||||
if (unlikely (!glyf.get_instruction_offsets (start_offset, end_offset,
|
||||
instruction_start, instruction_end)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
total += end_offset - start_offset - (*instruction_end - *instruction_start);
|
||||
total += end_offset - start_offset
|
||||
- ((*instruction_ranges)[instruction_ranges->length - 1]
|
||||
- (*instruction_ranges)[instruction_ranges->length - 2]);
|
||||
/* round2 so short loca will work */
|
||||
total += total % 2;
|
||||
}
|
||||
|
||||
*glyf_size = total;
|
||||
*use_short_loca = (total <= 131070);
|
||||
*loca_size = (glyph_ids.length + 1)
|
||||
* (*use_short_loca ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
|
||||
loca_data->is_short = (total <= 131070);
|
||||
loca_data->size = (plan->num_output_glyphs () + 1)
|
||||
* (loca_data->is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
|
||||
|
||||
DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
|
||||
total,
|
||||
*loca_size,
|
||||
*use_short_loca ? "short" : "long");
|
||||
loca_data->size,
|
||||
loca_data->is_short ? "short" : "long");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_write_loca_entry (unsigned int id,
|
||||
unsigned int offset,
|
||||
bool is_short,
|
||||
void *loca_prime,
|
||||
unsigned int loca_size)
|
||||
{
|
||||
unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
|
||||
if ((id + 1) * entry_size <= loca_size)
|
||||
{
|
||||
if (is_short) {
|
||||
((OT::HBUINT16*) loca_prime) [id].set (offset / 2);
|
||||
} else {
|
||||
((OT::HBUINT32*) loca_prime) [id].set (offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Offset was not written because the write is out of bounds.
|
||||
DEBUG_MSG(SUBSET,
|
||||
nullptr,
|
||||
"WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
|
||||
id,
|
||||
loca_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_components (hb_subset_plan_t * plan,
|
||||
char * glyph_start,
|
||||
unsigned int length)
|
||||
_update_components (const hb_subset_plan_t *plan,
|
||||
char *glyph_start,
|
||||
unsigned int length)
|
||||
{
|
||||
OT::glyf::CompositeGlyphHeader::Iterator iterator;
|
||||
if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
|
||||
|
@ -153,24 +184,35 @@ static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int l
|
|||
}
|
||||
|
||||
static bool
|
||||
_write_glyf_and_loca_prime (hb_subset_plan_t *plan,
|
||||
_write_glyf_and_loca_prime (const hb_subset_plan_t *plan,
|
||||
const OT::glyf::accelerator_t &glyf,
|
||||
const char *glyf_data,
|
||||
bool use_short_loca,
|
||||
hb_vector_t<unsigned int> &instruction_ranges,
|
||||
hb_vector_t<unsigned int> &instruction_ranges,
|
||||
unsigned int glyf_prime_size,
|
||||
char *glyf_prime_data /* OUT */,
|
||||
unsigned int loca_prime_size,
|
||||
char *loca_prime_data /* OUT */)
|
||||
loca_data_t *loca_prime /* OUT */)
|
||||
{
|
||||
hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
|
||||
char *glyf_prime_data_next = glyf_prime_data;
|
||||
|
||||
bool success = true;
|
||||
for (unsigned int i = 0; i < glyph_ids.length; i++)
|
||||
|
||||
|
||||
unsigned int i = 0;
|
||||
hb_codepoint_t new_gid;
|
||||
for (new_gid = 0; new_gid < plan->num_output_glyphs (); new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
|
||||
{
|
||||
// Empty glyph, add a loca entry and carry on.
|
||||
loca_prime->_write_loca_entry (new_gid,
|
||||
glyf_prime_data_next - glyf_prime_data);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
unsigned int start_offset, end_offset;
|
||||
if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
|
||||
if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) &&
|
||||
glyf.remove_padding (start_offset, &end_offset))))
|
||||
end_offset = start_offset = 0;
|
||||
|
||||
|
@ -182,9 +224,9 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
|
|||
if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
|
||||
{
|
||||
DEBUG_MSG(SUBSET,
|
||||
nullptr,
|
||||
"WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
|
||||
i, length);
|
||||
nullptr,
|
||||
"WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
|
||||
i, length);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -204,22 +246,20 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
|
|||
memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
|
||||
}
|
||||
|
||||
success = success && _write_loca_entry (i,
|
||||
glyf_prime_data_next - glyf_prime_data,
|
||||
use_short_loca,
|
||||
loca_prime_data,
|
||||
loca_prime_size);
|
||||
success = success && loca_prime->_write_loca_entry (new_gid,
|
||||
glyf_prime_data_next - glyf_prime_data);
|
||||
_update_components (plan, glyf_prime_data_next, length);
|
||||
|
||||
// TODO: don't align to two bytes if using long loca.
|
||||
glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
success = success && _write_loca_entry (glyph_ids.length,
|
||||
glyf_prime_data_next - glyf_prime_data,
|
||||
use_short_loca,
|
||||
loca_prime_data,
|
||||
loca_prime_size);
|
||||
// loca table has n+1 entries where the last entry signifies the end location of the last
|
||||
// glyph.
|
||||
success = success && loca_prime->_write_loca_entry (new_gid,
|
||||
glyf_prime_data_next - glyf_prime_data);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -228,52 +268,48 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
|
|||
const char *glyf_data,
|
||||
hb_subset_plan_t *plan,
|
||||
bool *use_short_loca,
|
||||
hb_blob_t **glyf_prime /* OUT */,
|
||||
hb_blob_t **loca_prime /* OUT */)
|
||||
hb_blob_t **glyf_prime_blob /* OUT */,
|
||||
hb_blob_t **loca_prime_blob /* OUT */)
|
||||
{
|
||||
// TODO(grieger): Sanity check allocation size for the new table.
|
||||
hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
|
||||
|
||||
loca_data_t loca_prime;
|
||||
unsigned int glyf_prime_size;
|
||||
unsigned int loca_prime_size;
|
||||
hb_vector_t<unsigned int> instruction_ranges;
|
||||
instruction_ranges.init ();
|
||||
|
||||
if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
|
||||
glyphs_to_retain,
|
||||
plan->drop_hints,
|
||||
use_short_loca,
|
||||
plan,
|
||||
&loca_prime,
|
||||
&glyf_prime_size,
|
||||
&loca_prime_size,
|
||||
&instruction_ranges))) {
|
||||
instruction_ranges.fini ();
|
||||
return false;
|
||||
}
|
||||
*use_short_loca = loca_prime.is_short;
|
||||
|
||||
char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
|
||||
char *loca_prime_data = (char *) calloc (1, loca_prime_size);
|
||||
loca_prime.data = (void *) calloc (1, loca_prime.size);
|
||||
if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
|
||||
*use_short_loca,
|
||||
instruction_ranges,
|
||||
glyf_prime_size, glyf_prime_data,
|
||||
loca_prime_size, loca_prime_data))) {
|
||||
&loca_prime))) {
|
||||
free (glyf_prime_data);
|
||||
free (loca_prime_data);
|
||||
free (loca_prime.data);
|
||||
instruction_ranges.fini ();
|
||||
return false;
|
||||
}
|
||||
instruction_ranges.fini ();
|
||||
|
||||
*glyf_prime = hb_blob_create (glyf_prime_data,
|
||||
glyf_prime_size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
glyf_prime_data,
|
||||
free);
|
||||
*loca_prime = hb_blob_create (loca_prime_data,
|
||||
loca_prime_size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
loca_prime_data,
|
||||
free);
|
||||
*glyf_prime_blob = hb_blob_create (glyf_prime_data,
|
||||
glyf_prime_size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
glyf_prime_data,
|
||||
free);
|
||||
*loca_prime_blob = hb_blob_create ((char *) loca_prime.data,
|
||||
loca_prime.size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
loca_prime.data,
|
||||
free);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,10 @@ hb_subset_input_create_or_fail ()
|
|||
|
||||
input->unicodes = hb_set_create ();
|
||||
input->glyphs = hb_set_create ();
|
||||
input->drop_hints = false;
|
||||
input->drop_layout = true;
|
||||
input->desubroutinize = false;
|
||||
input->retain_gids = false;
|
||||
|
||||
return input;
|
||||
}
|
||||
|
@ -144,3 +147,27 @@ hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
|
|||
{
|
||||
return subset_input->desubroutinize;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_set_retain_gids:
|
||||
* @subset_input: a subset_input.
|
||||
* @retain_gids: If true the subsetter will not renumber glyph ids.
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
|
||||
hb_bool_t retain_gids)
|
||||
{
|
||||
subset_input->retain_gids = retain_gids;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_input_get_retain_gids:
|
||||
* Returns: value of retain_gids.
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
|
||||
{
|
||||
return subset_input->retain_gids;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ struct hb_subset_input_t
|
|||
bool drop_hints : 1;
|
||||
bool drop_layout : 1;
|
||||
bool desubroutinize : 1;
|
||||
bool retain_gids : 1;
|
||||
/* TODO
|
||||
*
|
||||
* features
|
||||
|
|
|
@ -156,11 +156,32 @@ _populate_gids_to_retain (hb_face_t *face,
|
|||
}
|
||||
|
||||
static void
|
||||
_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
|
||||
hb_map_t *glyph_map)
|
||||
_create_old_gid_to_new_gid_map (const hb_face_t *face,
|
||||
bool retain_gids,
|
||||
const hb_vector_t<hb_codepoint_t> &glyphs,
|
||||
hb_map_t *glyph_map, /* OUT */
|
||||
hb_map_t *reverse_glyph_map, /* OUT */
|
||||
unsigned int *num_glyphs /* OUT */)
|
||||
{
|
||||
for (unsigned int i = 0; i < glyphs.length; i++) {
|
||||
glyph_map->set (glyphs[i], i);
|
||||
if (!retain_gids)
|
||||
{
|
||||
glyph_map->set (glyphs[i], i);
|
||||
reverse_glyph_map->set (i, glyphs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_map->set (glyphs[i], glyphs[i]);
|
||||
reverse_glyph_map->set (glyphs[i], glyphs[i]);
|
||||
}
|
||||
}
|
||||
if (!retain_gids || glyphs.length == 0)
|
||||
{
|
||||
*num_glyphs = glyphs.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
*num_glyphs = face->get_num_glyphs ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,19 +205,25 @@ hb_subset_plan_create (hb_face_t *face,
|
|||
plan->drop_layout = input->drop_layout;
|
||||
plan->desubroutinize = input->desubroutinize;
|
||||
plan->unicodes = hb_set_create();
|
||||
plan->glyphs.init();
|
||||
plan->glyphs_deprecated.init();
|
||||
plan->source = hb_face_reference (face);
|
||||
plan->dest = hb_face_builder_create ();
|
||||
plan->codepoint_to_glyph = hb_map_create();
|
||||
plan->glyph_map = hb_map_create();
|
||||
plan->glyphset = _populate_gids_to_retain (face,
|
||||
input->unicodes,
|
||||
!plan->drop_layout,
|
||||
plan->unicodes,
|
||||
plan->codepoint_to_glyph,
|
||||
&plan->glyphs);
|
||||
_create_old_gid_to_new_gid_map (plan->glyphs,
|
||||
plan->glyph_map);
|
||||
plan->reverse_glyph_map = hb_map_create();
|
||||
plan->_glyphset = _populate_gids_to_retain (face,
|
||||
input->unicodes,
|
||||
!plan->drop_layout,
|
||||
plan->unicodes,
|
||||
plan->codepoint_to_glyph,
|
||||
&plan->glyphs_deprecated);
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->retain_gids,
|
||||
plan->glyphs_deprecated,
|
||||
plan->glyph_map,
|
||||
plan->reverse_glyph_map,
|
||||
&plan->_num_output_glyphs);
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
@ -212,12 +239,13 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
|||
if (!hb_object_destroy (plan)) return;
|
||||
|
||||
hb_set_destroy (plan->unicodes);
|
||||
plan->glyphs.fini ();
|
||||
plan->glyphs_deprecated.fini ();
|
||||
hb_face_destroy (plan->source);
|
||||
hb_face_destroy (plan->dest);
|
||||
hb_map_destroy (plan->codepoint_to_glyph);
|
||||
hb_map_destroy (plan->glyph_map);
|
||||
hb_set_destroy (plan->glyphset);
|
||||
hb_map_destroy (plan->reverse_glyph_map);
|
||||
hb_set_destroy (plan->_glyphset);
|
||||
|
||||
free (plan);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "hb-subset-input.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
struct hb_subset_plan_t
|
||||
{
|
||||
|
@ -45,18 +46,54 @@ struct hb_subset_plan_t
|
|||
// For each cp that we'd like to retain maps to the corresponding gid.
|
||||
hb_set_t *unicodes;
|
||||
|
||||
hb_vector_t<hb_codepoint_t> glyphs;
|
||||
hb_set_t *glyphset;
|
||||
|
||||
// The glyph subset
|
||||
hb_map_t *codepoint_to_glyph;
|
||||
|
||||
// Old -> New glyph id mapping
|
||||
hb_map_t *glyph_map;
|
||||
hb_map_t *reverse_glyph_map;
|
||||
|
||||
// Deprecated members:
|
||||
hb_vector_t<hb_codepoint_t> glyphs_deprecated;
|
||||
|
||||
// Plan is only good for a specific source/dest so keep them with it
|
||||
hb_face_t *source;
|
||||
hb_face_t *dest;
|
||||
|
||||
bool new_gid_for_codepoint (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t *new_gid) const
|
||||
unsigned int _num_output_glyphs;
|
||||
hb_set_t *_glyphset;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* The set of input glyph ids which will be retained in the subset.
|
||||
*/
|
||||
inline const hb_set_t *
|
||||
glyphset () const
|
||||
{
|
||||
return _glyphset;
|
||||
}
|
||||
|
||||
/*
|
||||
* The total number of output glyphs in the final subset.
|
||||
*/
|
||||
inline unsigned int
|
||||
num_output_glyphs () const
|
||||
{
|
||||
return _num_output_glyphs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an output gid , returns true if that glyph id is an empty
|
||||
* glyph (ie. it's a gid that we are dropping all data for).
|
||||
*/
|
||||
inline bool is_empty_glyph (hb_codepoint_t gid) const
|
||||
{
|
||||
return !_glyphset->has (gid);
|
||||
}
|
||||
|
||||
inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
|
||||
hb_codepoint_t *new_gid) const
|
||||
{
|
||||
hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
|
||||
if (old_gid == HB_MAP_VALUE_INVALID)
|
||||
|
@ -65,8 +102,8 @@ struct hb_subset_plan_t
|
|||
return new_gid_for_old_gid (old_gid, new_gid);
|
||||
}
|
||||
|
||||
bool new_gid_for_old_gid (hb_codepoint_t old_gid,
|
||||
hb_codepoint_t *new_gid) const
|
||||
inline bool new_gid_for_old_gid (hb_codepoint_t old_gid,
|
||||
hb_codepoint_t *new_gid) const
|
||||
{
|
||||
hb_codepoint_t gid = glyph_map->get (old_gid);
|
||||
if (gid == HB_MAP_VALUE_INVALID)
|
||||
|
@ -76,7 +113,18 @@ struct hb_subset_plan_t
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
inline bool old_gid_for_new_gid (hb_codepoint_t new_gid,
|
||||
hb_codepoint_t *old_gid) const
|
||||
{
|
||||
hb_codepoint_t gid = reverse_glyph_map->get (new_gid);
|
||||
if (gid == HB_MAP_VALUE_INVALID)
|
||||
return false;
|
||||
|
||||
*old_gid = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
add_table (hb_tag_t tag,
|
||||
hb_blob_t *contents)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ _plan_estimate_subset_table_size (hb_subset_plan_t *plan,
|
|||
unsigned int table_len)
|
||||
{
|
||||
unsigned int src_glyphs = plan->source->get_num_glyphs ();
|
||||
unsigned int dst_glyphs = plan->glyphset->get_population ();
|
||||
unsigned int dst_glyphs = plan->glyphset ()->get_population ();
|
||||
|
||||
if (unlikely (!src_glyphs))
|
||||
return 512 + table_len;
|
||||
|
|
|
@ -72,6 +72,12 @@ hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
|
|||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
|
||||
hb_bool_t retain_gids);
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);
|
||||
|
||||
/* hb_subset () */
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset (hb_face_t *source, hb_subset_input_t *input);
|
||||
|
|
|
@ -38,9 +38,9 @@ HB_BEGIN_DECLS
|
|||
|
||||
#define HB_VERSION_MAJOR 2
|
||||
#define HB_VERSION_MINOR 3
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_MICRO 1
|
||||
|
||||
#define HB_VERSION_STRING "2.3.0"
|
||||
#define HB_VERSION_STRING "2.3.1"
|
||||
|
||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) <= \
|
||||
|
|
Binary file not shown.
|
@ -257,6 +257,31 @@ test_subset_glyf_strip_hints_invalid (void)
|
|||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
static void
|
||||
test_subset_glyf_retain_gids (void)
|
||||
{
|
||||
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
|
||||
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.retaingids.ttf");
|
||||
|
||||
hb_set_t *codepoints = hb_set_create();
|
||||
hb_face_t *face_abc_subset;
|
||||
hb_set_add (codepoints, 97);
|
||||
hb_set_add (codepoints, 99);
|
||||
|
||||
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
|
||||
hb_subset_input_set_retain_gids (input, true);
|
||||
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
|
||||
hb_set_destroy (codepoints);
|
||||
|
||||
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
|
||||
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
|
||||
check_maxp_num_glyphs(face_abc_subset, 4, true);
|
||||
|
||||
hb_face_destroy (face_abc_subset);
|
||||
hb_face_destroy (face_abc);
|
||||
hb_face_destroy (face_ac);
|
||||
}
|
||||
|
||||
// TODO(grieger): test for long loca generation.
|
||||
|
||||
int
|
||||
|
@ -272,6 +297,7 @@ main (int argc, char **argv)
|
|||
hb_test_add (test_subset_glyf_with_components);
|
||||
hb_test_add (test_subset_glyf_with_gsub);
|
||||
hb_test_add (test_subset_glyf_without_gsub);
|
||||
hb_test_add (test_subset_glyf_retain_gids);
|
||||
|
||||
return hb_test_run();
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
--no-hinting
|
||||
--retain-gids
|
|
@ -0,0 +1 @@
|
|||
--retain-gids
|
|
@ -4,6 +4,8 @@ Roboto-Regular.abc.ttf
|
|||
PROFILES:
|
||||
default.txt
|
||||
drop-hints.txt
|
||||
drop-hints-retain-gids.txt
|
||||
retain-gids.txt
|
||||
|
||||
SUBSETS:
|
||||
abc
|
||||
|
|
|
@ -91,6 +91,7 @@ struct subset_consumer_t
|
|||
{
|
||||
hb_subset_input_set_drop_layout (input, !subset_options.keep_layout);
|
||||
hb_subset_input_set_drop_hints (input, subset_options.drop_hints);
|
||||
hb_subset_input_set_retain_gids (input, subset_options.retain_gids);
|
||||
hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize);
|
||||
|
||||
hb_face_t *face = hb_font_get_face (font);
|
||||
|
|
|
@ -977,6 +977,7 @@ subset_options_t::add_options (option_parser_t *parser)
|
|||
{
|
||||
{"layout", 0, 0, G_OPTION_ARG_NONE, &this->keep_layout, "Keep OpenType Layout tables", nullptr},
|
||||
{"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->drop_hints, "Whether to drop hints", nullptr},
|
||||
{"retain-gids", 0, 0, G_OPTION_ARG_NONE, &this->retain_gids, "If set don't renumber glyph ids in the subset.", nullptr},
|
||||
{"desubroutinize", 0, 0, G_OPTION_ARG_NONE, &this->desubroutinize, "Remove CFF/CFF2 use of subroutines", nullptr},
|
||||
|
||||
{nullptr}
|
||||
|
|
|
@ -675,6 +675,7 @@ struct subset_options_t : option_group_t
|
|||
{
|
||||
keep_layout = false;
|
||||
drop_hints = false;
|
||||
retain_gids = false;
|
||||
desubroutinize = false;
|
||||
|
||||
add_options (parser);
|
||||
|
@ -684,6 +685,7 @@ struct subset_options_t : option_group_t
|
|||
|
||||
hb_bool_t keep_layout;
|
||||
hb_bool_t drop_hints;
|
||||
hb_bool_t retain_gids;
|
||||
hb_bool_t desubroutinize;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue