[subset] Switch to using hb_map_t inside of hb_subset_plan_t.
This commit is contained in:
parent
b3d45de6cf
commit
251cc977e9
|
@ -28,6 +28,7 @@
|
||||||
#define HB_OT_CMAP_TABLE_HH
|
#define HB_OT_CMAP_TABLE_HH
|
||||||
|
|
||||||
#include "hb-open-type-private.hh"
|
#include "hb-open-type-private.hh"
|
||||||
|
#include "hb-set-private.hh"
|
||||||
#include "hb-subset-plan.hh"
|
#include "hb-subset-plan.hh"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -111,7 +112,7 @@ struct CmapSubtableFormat4
|
||||||
{
|
{
|
||||||
hb_codepoint_t cp = segments[i].start_code;
|
hb_codepoint_t cp = segments[i].start_code;
|
||||||
hb_codepoint_t start_gid = 0;
|
hb_codepoint_t start_gid = 0;
|
||||||
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &start_gid) && cp != 0xFFFF))
|
if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
id_delta[i].set (start_gid - segments[i].start_code);
|
id_delta[i].set (start_gid - segments[i].start_code);
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,7 +140,7 @@ struct CmapSubtableFormat4
|
||||||
{
|
{
|
||||||
hb_codepoint_t cp = segments[i].start_code + j;
|
hb_codepoint_t cp = segments[i].start_code + j;
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
|
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
glyph_id_array[j].set (new_gid);
|
glyph_id_array[j].set (new_gid);
|
||||||
}
|
}
|
||||||
|
@ -176,10 +177,11 @@ struct CmapSubtableFormat4
|
||||||
{
|
{
|
||||||
segment_plan *segment = nullptr;
|
segment_plan *segment = nullptr;
|
||||||
hb_codepoint_t last_gid = 0;
|
hb_codepoint_t last_gid = 0;
|
||||||
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
|
|
||||||
hb_codepoint_t cp = plan->codepoints[i];
|
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||||
|
while (plan->unicodes->next (&cp)) {
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
|
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
||||||
return false;
|
return false;
|
||||||
|
@ -494,11 +496,11 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
||||||
hb_vector_t<CmapSubtableLongGroup> *groups)
|
hb_vector_t<CmapSubtableLongGroup> *groups)
|
||||||
{
|
{
|
||||||
CmapSubtableLongGroup *group = nullptr;
|
CmapSubtableLongGroup *group = nullptr;
|
||||||
for (unsigned int i = 0; i < plan->codepoints.len; i++) {
|
|
||||||
|
|
||||||
hb_codepoint_t cp = plan->codepoints[i];
|
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||||
|
while (plan->unicodes->next (&cp)) {
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
|
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||||
{
|
{
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
||||||
return false;
|
return false;
|
||||||
|
@ -882,7 +884,7 @@ struct cmap
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
dest,
|
dest,
|
||||||
free);
|
free);
|
||||||
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime);
|
bool result = plan->add_table (HB_OT_TAG_cmap, cmap_prime);
|
||||||
hb_blob_destroy (cmap_prime);
|
hb_blob_destroy (cmap_prime);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,9 @@ struct glyf
|
||||||
bool success = true;
|
bool success = true;
|
||||||
bool use_short_loca = false;
|
bool use_short_loca = false;
|
||||||
if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
|
if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
|
||||||
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_glyf, glyf_prime);
|
success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
|
||||||
success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime);
|
success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
|
||||||
success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest);
|
success = success && _add_head_and_set_loca_version (plan, use_short_loca);
|
||||||
} else {
|
} else {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,9 @@ struct glyf
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_t *dest)
|
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
|
||||||
{
|
{
|
||||||
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (source, HB_OT_TAG_head));
|
hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
|
||||||
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
|
hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
|
||||||
hb_blob_destroy (head_blob);
|
hb_blob_destroy (head_blob);
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ struct glyf
|
||||||
|
|
||||||
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
|
||||||
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
|
head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
|
||||||
bool success = hb_subset_face_add_table (dest, HB_OT_TAG_head, head_prime_blob);
|
bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
|
||||||
|
|
||||||
hb_blob_destroy (head_prime_blob);
|
hb_blob_destroy (head_prime_blob);
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -59,13 +59,13 @@ struct DeviceRecord
|
||||||
|
|
||||||
inline unsigned int len () const
|
inline unsigned int len () const
|
||||||
{
|
{
|
||||||
return this->subset_plan->gids_to_retain_sorted.len;
|
return this->subset_plan->glyphs.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const HBUINT8* operator [] (unsigned int i) const
|
inline const HBUINT8* operator [] (unsigned int i) const
|
||||||
{
|
{
|
||||||
if (unlikely (i >= len())) return nullptr;
|
if (unlikely (i >= len())) return nullptr;
|
||||||
hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
|
hb_codepoint_t gid = this->subset_plan->glyphs [i];
|
||||||
|
|
||||||
const HBUINT8* width = &(this->source_device_record->widths[gid]);
|
const HBUINT8* width = &(this->source_device_record->widths[gid]);
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ struct hdmx
|
||||||
|
|
||||||
this->version.set (source_hdmx->version);
|
this->version.set (source_hdmx->version);
|
||||||
this->num_records.set (source_hdmx->num_records);
|
this->num_records.set (source_hdmx->num_records);
|
||||||
this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len));
|
this->size_device_record.set (DeviceRecord::get_size (plan->glyphs.len));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < source_hdmx->num_records; i++)
|
for (unsigned int i = 0; i < source_hdmx->num_records; i++)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ struct hdmx
|
||||||
|
|
||||||
static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
|
static inline size_t get_subsetted_size (hb_subset_plan_t *plan)
|
||||||
{
|
{
|
||||||
return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len);
|
return min_size + DeviceRecord::get_size (plan->glyphs.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool subset (hb_subset_plan_t *plan) const
|
inline bool subset (hb_subset_plan_t *plan) const
|
||||||
|
@ -189,7 +189,7 @@ struct hdmx
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
dest,
|
dest,
|
||||||
free);
|
free);
|
||||||
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob);
|
bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
|
||||||
hb_blob_destroy (hdmx_prime_blob);
|
hb_blob_destroy (hdmx_prime_blob);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -81,7 +81,7 @@ struct hmtxvmtx
|
||||||
H *table = (H *) hb_blob_get_data (dest_blob, &length);
|
H *table = (H *) hb_blob_get_data (dest_blob, &length);
|
||||||
table->numberOfLongMetrics.set (num_hmetrics);
|
table->numberOfLongMetrics.set (num_hmetrics);
|
||||||
|
|
||||||
bool result = hb_subset_plan_add_table (plan, H::tableTag, dest_blob);
|
bool result = plan->add_table (H::tableTag, dest_blob);
|
||||||
hb_blob_destroy (dest_blob);
|
hb_blob_destroy (dest_blob);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -94,7 +94,7 @@ struct hmtxvmtx
|
||||||
|
|
||||||
/* All the trailing glyphs with the same advance can use one LongMetric
|
/* All the trailing glyphs with the same advance can use one LongMetric
|
||||||
* and just keep LSB */
|
* and just keep LSB */
|
||||||
hb_vector_t<hb_codepoint_t> &gids = plan->gids_to_retain_sorted;
|
hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
|
||||||
unsigned int num_advances = gids.len;
|
unsigned int num_advances = gids.len;
|
||||||
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
|
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
|
||||||
while (num_advances > 1
|
while (num_advances > 1
|
||||||
|
@ -178,7 +178,7 @@ struct hmtxvmtx
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
dest,
|
dest,
|
||||||
free);
|
free);
|
||||||
bool success = hb_subset_plan_add_table (plan, T::tableTag, result);
|
bool success = plan->add_table (T::tableTag, result);
|
||||||
hb_blob_destroy (result);
|
hb_blob_destroy (result);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,11 +109,11 @@ struct maxp
|
||||||
}
|
}
|
||||||
OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
|
OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
|
||||||
|
|
||||||
maxp_prime->set_num_glyphs (plan->gids_to_retain_sorted.len);
|
maxp_prime->set_num_glyphs (plan->glyphs.len);
|
||||||
if (plan->drop_hints)
|
if (plan->drop_hints)
|
||||||
drop_hint_fields (plan, maxp_prime);
|
drop_hint_fields (plan, maxp_prime);
|
||||||
|
|
||||||
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_maxp, maxp_prime_blob);
|
bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
|
||||||
hb_blob_destroy (maxp_prime_blob);
|
hb_blob_destroy (maxp_prime_blob);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,26 +63,25 @@ struct os2
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t min_cp, max_cp;
|
uint16_t min_cp, max_cp;
|
||||||
find_min_and_max_codepoint (plan->codepoints, &min_cp, &max_cp);
|
find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
|
||||||
os2_prime->usFirstCharIndex.set (min_cp);
|
os2_prime->usFirstCharIndex.set (min_cp);
|
||||||
os2_prime->usLastCharIndex.set (max_cp);
|
os2_prime->usLastCharIndex.set (max_cp);
|
||||||
|
|
||||||
_update_unicode_ranges (plan->codepoints, os2_prime->ulUnicodeRange);
|
_update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
|
||||||
bool result = hb_subset_plan_add_table(plan, HB_OT_TAG_os2, os2_prime_blob);
|
bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
|
||||||
|
|
||||||
hb_blob_destroy (os2_prime_blob);
|
hb_blob_destroy (os2_prime_blob);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _update_unicode_ranges (const hb_vector_t<hb_codepoint_t> &codepoints,
|
inline void _update_unicode_ranges (const hb_set_t *codepoints,
|
||||||
HBUINT32 ulUnicodeRange[4]) const
|
HBUINT32 ulUnicodeRange[4]) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < 4; i++)
|
for (unsigned int i = 0; i < 4; i++)
|
||||||
ulUnicodeRange[i].set (0);
|
ulUnicodeRange[i].set (0);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < codepoints.len; i++)
|
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||||
{
|
while (codepoints->next (&cp)) {
|
||||||
hb_codepoint_t cp = codepoints[i];
|
|
||||||
unsigned int bit = hb_get_unicode_range_bit (cp);
|
unsigned int bit = hb_get_unicode_range_bit (cp);
|
||||||
if (bit < 128)
|
if (bit < 128)
|
||||||
{
|
{
|
||||||
|
@ -101,28 +100,12 @@ struct os2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void find_min_and_max_codepoint (const hb_vector_t<hb_codepoint_t> &codepoints,
|
static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
|
||||||
uint16_t *min_cp, /* OUT */
|
uint16_t *min_cp, /* OUT */
|
||||||
uint16_t *max_cp /* OUT */)
|
uint16_t *max_cp /* OUT */)
|
||||||
{
|
{
|
||||||
hb_codepoint_t min = -1, max = 0;
|
*min_cp = codepoints->get_min ();
|
||||||
|
*max_cp = codepoints->get_max ();
|
||||||
for (unsigned int i = 0; i < codepoints.len; i++)
|
|
||||||
{
|
|
||||||
hb_codepoint_t cp = codepoints[i];
|
|
||||||
if (cp < min)
|
|
||||||
min = cp;
|
|
||||||
if (cp > max)
|
|
||||||
max = cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min > 0xFFFF)
|
|
||||||
min = 0xFFFF;
|
|
||||||
if (max > 0xFFFF)
|
|
||||||
max = 0xFFFF;
|
|
||||||
|
|
||||||
*min_cp = min;
|
|
||||||
*max_cp = max;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum font_page_t {
|
enum font_page_t {
|
||||||
|
|
|
@ -99,7 +99,7 @@ struct post
|
||||||
}
|
}
|
||||||
|
|
||||||
post_prime->version.major.set (3); // Version 3 does not have any glyph names.
|
post_prime->version.major.set (3); // Version 3 does not have any glyph names.
|
||||||
bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_post, post_prime_blob);
|
bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
|
||||||
hb_blob_destroy (post_prime_blob);
|
hb_blob_destroy (post_prime_blob);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -130,9 +130,8 @@ _update_components (hb_subset_plan_t * plan,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (!hb_subset_plan_new_gid_for_old_id (plan,
|
if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
|
||||||
iterator.current->glyphIndex,
|
&new_gid))
|
||||||
&new_gid))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
|
((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
|
||||||
|
@ -165,7 +164,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan,
|
||||||
unsigned int loca_prime_size,
|
unsigned int loca_prime_size,
|
||||||
char *loca_prime_data /* OUT */)
|
char *loca_prime_data /* OUT */)
|
||||||
{
|
{
|
||||||
hb_vector_t<hb_codepoint_t> &glyph_ids = plan->gids_to_retain_sorted;
|
hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
|
||||||
char *glyf_prime_data_next = glyf_prime_data;
|
char *glyf_prime_data_next = glyf_prime_data;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
@ -234,7 +233,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
|
||||||
hb_blob_t **loca_prime /* OUT */)
|
hb_blob_t **loca_prime /* OUT */)
|
||||||
{
|
{
|
||||||
// TODO(grieger): Sanity check allocation size for the new table.
|
// TODO(grieger): Sanity check allocation size for the new table.
|
||||||
hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->gids_to_retain_sorted;
|
hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
|
||||||
|
|
||||||
unsigned int glyf_prime_size;
|
unsigned int glyf_prime_size;
|
||||||
unsigned int loca_prime_size;
|
unsigned int loca_prime_size;
|
||||||
|
|
|
@ -24,78 +24,14 @@
|
||||||
* Google Author(s): Garret Rieger, Roderick Sheeter
|
* Google Author(s): Garret Rieger, Roderick Sheeter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "hb-map-private.hh"
|
||||||
#include "hb-subset-private.hh"
|
#include "hb-subset-private.hh"
|
||||||
|
#include "hb-set-private.hh"
|
||||||
|
|
||||||
#include "hb-subset-plan.hh"
|
#include "hb-subset-plan.hh"
|
||||||
#include "hb-ot-cmap-table.hh"
|
#include "hb-ot-cmap-table.hh"
|
||||||
#include "hb-ot-glyf-table.hh"
|
#include "hb-ot-glyf-table.hh"
|
||||||
|
|
||||||
static int
|
|
||||||
_hb_codepoint_t_cmp (const void *pa, const void *pb)
|
|
||||||
{
|
|
||||||
hb_codepoint_t a = * (hb_codepoint_t *) pa;
|
|
||||||
hb_codepoint_t b = * (hb_codepoint_t *) pb;
|
|
||||||
|
|
||||||
return a < b ? -1 : a > b ? +1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_bool_t
|
|
||||||
hb_subset_plan_new_gid_for_codepoint (const hb_subset_plan_t *plan,
|
|
||||||
hb_codepoint_t codepoint,
|
|
||||||
hb_codepoint_t *new_gid)
|
|
||||||
{
|
|
||||||
// TODO actual map, delete this garbage.
|
|
||||||
for (unsigned int i = 0; i < plan->codepoints.len; i++)
|
|
||||||
{
|
|
||||||
if (plan->codepoints[i] != codepoint) continue;
|
|
||||||
if (!hb_subset_plan_new_gid_for_old_id(plan, plan->gids_to_retain[i], new_gid))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_bool_t
|
|
||||||
hb_subset_plan_new_gid_for_old_id (const hb_subset_plan_t *plan,
|
|
||||||
hb_codepoint_t old_gid,
|
|
||||||
hb_codepoint_t *new_gid)
|
|
||||||
{
|
|
||||||
// the index in old_gids is the new gid; only up to codepoints.len are valid
|
|
||||||
for (unsigned int i = 0; i < plan->gids_to_retain_sorted.len; i++)
|
|
||||||
{
|
|
||||||
if (plan->gids_to_retain_sorted[i] == old_gid)
|
|
||||||
{
|
|
||||||
*new_gid = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_bool_t
|
|
||||||
hb_subset_plan_add_table (hb_subset_plan_t *plan,
|
|
||||||
hb_tag_t tag,
|
|
||||||
hb_blob_t *contents)
|
|
||||||
{
|
|
||||||
hb_blob_t *source_blob = plan->source->reference_table (tag);
|
|
||||||
DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes", HB_UNTAG(tag), hb_blob_get_length (contents), hb_blob_get_length (source_blob));
|
|
||||||
hb_blob_destroy (source_blob);
|
|
||||||
return hb_subset_face_add_table(plan->dest, tag, contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_populate_codepoints (hb_set_t *input_codepoints,
|
|
||||||
hb_vector_t<hb_codepoint_t>& plan_codepoints)
|
|
||||||
{
|
|
||||||
plan_codepoints.alloc (hb_set_get_population (input_codepoints));
|
|
||||||
hb_codepoint_t cp = -1;
|
|
||||||
while (hb_set_next (input_codepoints, &cp))
|
|
||||||
plan_codepoints.push(cp);
|
|
||||||
plan_codepoints.qsort (_hb_codepoint_t_cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
||||||
hb_codepoint_t gid,
|
hb_codepoint_t gid,
|
||||||
|
@ -119,58 +55,66 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_populate_gids_to_retain (hb_face_t *face,
|
_populate_gids_to_retain (hb_face_t *face,
|
||||||
hb_vector_t<hb_codepoint_t>& codepoints,
|
const hb_set_t *unicodes,
|
||||||
hb_vector_t<hb_codepoint_t>& old_gids,
|
hb_set_t *unicodes_to_retain,
|
||||||
hb_vector_t<hb_codepoint_t>& old_gids_sorted)
|
hb_map_t *codepoint_to_glyph,
|
||||||
|
hb_vector_t<hb_codepoint_t> *glyphs)
|
||||||
{
|
{
|
||||||
OT::cmap::accelerator_t cmap;
|
OT::cmap::accelerator_t cmap;
|
||||||
OT::glyf::accelerator_t glyf;
|
OT::glyf::accelerator_t glyf;
|
||||||
cmap.init (face);
|
cmap.init (face);
|
||||||
glyf.init (face);
|
glyf.init (face);
|
||||||
|
|
||||||
hb_auto_t<hb_vector_t<unsigned int> > bad_indices;
|
hb_set_t *initial_gids_to_retain = hb_set_create ();
|
||||||
|
initial_gids_to_retain->add (0); // Not-def
|
||||||
|
|
||||||
old_gids.alloc (codepoints.len);
|
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||||
for (unsigned int i = 0; i < codepoints.len; i++)
|
while (unicodes->next (&cp))
|
||||||
{
|
{
|
||||||
hb_codepoint_t gid;
|
hb_codepoint_t gid;
|
||||||
if (!cmap.get_nominal_glyph (codepoints[i], &gid))
|
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||||
{
|
{
|
||||||
gid = -1;
|
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||||
bad_indices.push (i);
|
continue;
|
||||||
}
|
}
|
||||||
old_gids.push (gid);
|
unicodes_to_retain->add (cp);
|
||||||
}
|
codepoint_to_glyph->set (cp, gid);
|
||||||
|
initial_gids_to_retain->add (gid);
|
||||||
/* Generally there shouldn't be any */
|
|
||||||
while (bad_indices.len > 0)
|
|
||||||
{
|
|
||||||
unsigned int i = bad_indices[bad_indices.len - 1];
|
|
||||||
bad_indices.pop ();
|
|
||||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", codepoints[i]);
|
|
||||||
codepoints.remove (i);
|
|
||||||
old_gids.remove (i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate a full set of glyphs to retain by adding all referenced
|
// Populate a full set of glyphs to retain by adding all referenced
|
||||||
// composite glyphs.
|
// composite glyphs.
|
||||||
// TODO expand with glyphs reached by G*
|
// TODO expand with glyphs reached by G*
|
||||||
hb_set_t * all_gids_to_retain = hb_set_create ();
|
|
||||||
_add_gid_and_children (glyf, 0, all_gids_to_retain);
|
|
||||||
for (unsigned int i = 0; i < old_gids.len; i++)
|
|
||||||
_add_gid_and_children (glyf, old_gids[i], all_gids_to_retain);
|
|
||||||
|
|
||||||
// Transfer to a sorted list.
|
|
||||||
old_gids_sorted.alloc (hb_set_get_population (all_gids_to_retain));
|
|
||||||
hb_codepoint_t gid = HB_SET_VALUE_INVALID;
|
hb_codepoint_t gid = HB_SET_VALUE_INVALID;
|
||||||
while (hb_set_next (all_gids_to_retain, &gid))
|
hb_set_t *all_gids_to_retain = hb_set_create ();
|
||||||
old_gids_sorted.push (gid);
|
while (initial_gids_to_retain->next (&gid))
|
||||||
|
{
|
||||||
|
_add_gid_and_children (glyf, gid, all_gids_to_retain);
|
||||||
|
}
|
||||||
|
hb_set_destroy (initial_gids_to_retain);
|
||||||
|
|
||||||
|
glyphs->alloc (all_gids_to_retain->get_population ());
|
||||||
|
gid = HB_SET_VALUE_INVALID;
|
||||||
|
while (all_gids_to_retain->next (&gid))
|
||||||
|
{
|
||||||
|
glyphs->push (gid);
|
||||||
|
}
|
||||||
|
|
||||||
hb_set_destroy (all_gids_to_retain);
|
hb_set_destroy (all_gids_to_retain);
|
||||||
glyf.fini ();
|
glyf.fini ();
|
||||||
cmap.fini ();
|
cmap.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
|
||||||
|
hb_map_t *glyph_map)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < glyphs.len; i++) {
|
||||||
|
glyph_map->set (glyphs[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_subset_plan_create:
|
* hb_subset_plan_create:
|
||||||
* Computes a plan for subsetting the supplied face according
|
* Computes a plan for subsetting the supplied face according
|
||||||
|
@ -188,18 +132,21 @@ hb_subset_plan_create (hb_face_t *face,
|
||||||
{
|
{
|
||||||
hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
|
hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
|
||||||
|
|
||||||
plan->codepoints.init();
|
plan->drop_hints = input->drop_hints;
|
||||||
plan->gids_to_retain.init();
|
plan->unicodes = hb_set_create();
|
||||||
plan->gids_to_retain_sorted.init();
|
plan->glyphs.init();
|
||||||
plan->source = hb_face_reference (face);
|
plan->source = hb_face_reference (face);
|
||||||
plan->dest = hb_subset_face_create ();
|
plan->dest = hb_subset_face_create ();
|
||||||
plan->drop_hints = input->drop_hints;
|
plan->codepoint_to_glyph = hb_map_create();
|
||||||
|
plan->glyph_map = hb_map_create();
|
||||||
|
|
||||||
_populate_codepoints (input->unicodes, plan->codepoints);
|
|
||||||
_populate_gids_to_retain (face,
|
_populate_gids_to_retain (face,
|
||||||
plan->codepoints,
|
input->unicodes,
|
||||||
plan->gids_to_retain,
|
plan->unicodes,
|
||||||
plan->gids_to_retain_sorted);
|
plan->codepoint_to_glyph,
|
||||||
|
&plan->glyphs);
|
||||||
|
_create_old_gid_to_new_gid_map (plan->glyphs,
|
||||||
|
plan->glyph_map);
|
||||||
|
|
||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
@ -214,12 +161,12 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
||||||
{
|
{
|
||||||
if (!hb_object_destroy (plan)) return;
|
if (!hb_object_destroy (plan)) return;
|
||||||
|
|
||||||
plan->codepoints.fini ();
|
hb_set_destroy (plan->unicodes);
|
||||||
plan->gids_to_retain.fini ();
|
plan->glyphs.fini();
|
||||||
plan->gids_to_retain_sorted.fini ();
|
|
||||||
|
|
||||||
hb_face_destroy (plan->source);
|
hb_face_destroy (plan->source);
|
||||||
hb_face_destroy (plan->dest);
|
hb_face_destroy (plan->dest);
|
||||||
|
hb_map_destroy (plan->codepoint_to_glyph);
|
||||||
|
hb_map_destroy (plan->glyph_map);
|
||||||
|
|
||||||
free (plan);
|
free (plan);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
#include "hb-private.hh"
|
#include "hb-private.hh"
|
||||||
|
|
||||||
#include "hb-subset.h"
|
#include "hb-subset.h"
|
||||||
|
#include "hb-subset-private.hh"
|
||||||
|
|
||||||
#include "hb-object-private.hh"
|
#include "hb-object-private.hh"
|
||||||
|
#include "hb-map-private.hh"
|
||||||
|
|
||||||
struct hb_subset_plan_t {
|
struct hb_subset_plan_t {
|
||||||
hb_object_header_t header;
|
hb_object_header_t header;
|
||||||
|
@ -39,22 +41,55 @@ struct hb_subset_plan_t {
|
||||||
|
|
||||||
hb_bool_t drop_hints;
|
hb_bool_t drop_hints;
|
||||||
|
|
||||||
// TODO(Q1) actual map, drop this crap
|
// For each cp that we'd like to retain maps to the corresponding gid.
|
||||||
// Look at me ma, I'm a poor mans map codepoint : new gid
|
hb_set_t *unicodes;
|
||||||
// codepoints is sorted and aligned with gids_to_retain.
|
|
||||||
|
|
||||||
// These first two lists provide a mapping from cp -> gid
|
|
||||||
// As a result it does not list the full set of glyphs to retain.
|
|
||||||
hb_vector_t<hb_codepoint_t> codepoints;
|
|
||||||
hb_vector_t<hb_codepoint_t> gids_to_retain;
|
|
||||||
|
|
||||||
// This list contains the complete set of glyphs to retain and may contain
|
// This list contains the complete set of glyphs to retain and may contain
|
||||||
// more glyphs then the lists above.
|
// more glyphs then the lists above.
|
||||||
hb_vector_t<hb_codepoint_t> gids_to_retain_sorted;
|
hb_vector_t<hb_codepoint_t> glyphs;
|
||||||
|
|
||||||
|
hb_map_t *codepoint_to_glyph;
|
||||||
|
hb_map_t *glyph_map;
|
||||||
|
|
||||||
// Plan is only good for a specific source/dest so keep them with it
|
// Plan is only good for a specific source/dest so keep them with it
|
||||||
hb_face_t *source;
|
hb_face_t *source;
|
||||||
hb_face_t *dest;
|
hb_face_t *dest;
|
||||||
|
|
||||||
|
inline hb_bool_t
|
||||||
|
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)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return new_gid_for_old_gid (old_gid, new_gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline hb_bool_t
|
||||||
|
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)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*new_gid = gid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline hb_bool_t
|
||||||
|
add_table (hb_tag_t tag,
|
||||||
|
hb_blob_t *contents)
|
||||||
|
{
|
||||||
|
hb_blob_t *source_blob = source->reference_table (tag);
|
||||||
|
DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes",
|
||||||
|
HB_UNTAG(tag),
|
||||||
|
hb_blob_get_length (contents),
|
||||||
|
hb_blob_get_length (source_blob));
|
||||||
|
hb_blob_destroy (source_blob);
|
||||||
|
return hb_subset_face_add_table(dest, tag, contents);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct hb_subset_plan_t hb_subset_plan_t;
|
typedef struct hb_subset_plan_t hb_subset_plan_t;
|
||||||
|
@ -64,21 +99,6 @@ hb_subset_plan_create (hb_face_t *face,
|
||||||
hb_subset_profile_t *profile,
|
hb_subset_profile_t *profile,
|
||||||
hb_subset_input_t *input);
|
hb_subset_input_t *input);
|
||||||
|
|
||||||
HB_INTERNAL hb_bool_t
|
|
||||||
hb_subset_plan_new_gid_for_old_id (const hb_subset_plan_t *plan,
|
|
||||||
hb_codepoint_t old_gid,
|
|
||||||
hb_codepoint_t *new_gid /* OUT */);
|
|
||||||
|
|
||||||
HB_INTERNAL hb_bool_t
|
|
||||||
hb_subset_plan_new_gid_for_codepoint (const hb_subset_plan_t *plan,
|
|
||||||
hb_codepoint_t codepont,
|
|
||||||
hb_codepoint_t *new_gid /* OUT */);
|
|
||||||
|
|
||||||
HB_INTERNAL hb_bool_t
|
|
||||||
hb_subset_plan_add_table (hb_subset_plan_t *plan,
|
|
||||||
hb_tag_t tag,
|
|
||||||
hb_blob_t *contents);
|
|
||||||
|
|
||||||
HB_INTERNAL void
|
HB_INTERNAL void
|
||||||
hb_subset_plan_destroy (hb_subset_plan_t *plan);
|
hb_subset_plan_destroy (hb_subset_plan_t *plan);
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,7 @@ _subset_table (hb_subset_plan_t *plan,
|
||||||
default:
|
default:
|
||||||
hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
|
hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
|
||||||
if (likely (source_table))
|
if (likely (source_table))
|
||||||
result = hb_subset_plan_add_table(plan, tag, source_table);
|
result = plan->add_table(tag, source_table);
|
||||||
else
|
else
|
||||||
result = false;
|
result = false;
|
||||||
hb_blob_destroy (source_table);
|
hb_blob_destroy (source_table);
|
||||||
|
|
Loading…
Reference in New Issue