Merge branch 'master' into bitops
This commit is contained in:
commit
fe8f40a418
29
TODO
29
TODO
@ -1,24 +1,14 @@
|
||||
General fixes:
|
||||
=============
|
||||
|
||||
- AAT 'morx' implementation.
|
||||
|
||||
- Return "safe-to-break" bit from shaping.
|
||||
|
||||
- Implement 'rand' feature.
|
||||
|
||||
- mask propagation? (when ligation, "or" the masks).
|
||||
|
||||
|
||||
API issues:
|
||||
===========
|
||||
|
||||
- API to accept a list of languages?
|
||||
|
||||
- Add init_func to font_funcs. Adjust ft.
|
||||
|
||||
- 'const' for getter APIs? (use mutable internally)
|
||||
|
||||
- Remove hb_ot_shape_glyphs_closure()?
|
||||
|
||||
|
||||
@ -39,7 +29,7 @@ API additions
|
||||
|
||||
- Add query / enumeration API for aalt-like features?
|
||||
|
||||
- SFNT api? get_num_faces? get_table_tags? (there's something in stash)
|
||||
- SFNT api? get_num_faces?
|
||||
|
||||
- Add segmentation API
|
||||
|
||||
@ -50,20 +40,3 @@ hb-view / hb-shape enhancements:
|
||||
===============================
|
||||
|
||||
- Add --width, --height, --auto-size, --ink-box, --align, etc?
|
||||
|
||||
|
||||
Tests to write:
|
||||
==============
|
||||
|
||||
- ot-layout enumeration API (needs font)
|
||||
|
||||
- Finish test-shape.c, grep for TODO
|
||||
|
||||
- Finish test-unicode.c, grep for TODO
|
||||
|
||||
- GObject, FreeType, etc
|
||||
|
||||
- hb_cache_t and relatives
|
||||
|
||||
- hb_feature_to/from_string
|
||||
- hb_buffer_[sg]et_contents
|
||||
|
@ -344,8 +344,7 @@ struct hb_buffer_t {
|
||||
inline void
|
||||
unsafe_to_break_all (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
unsafe_to_break_impl (0, len);
|
||||
}
|
||||
inline void
|
||||
safe_to_break_all (void)
|
||||
|
@ -1244,8 +1244,6 @@ resize_and_retry:
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
else
|
||||
@ -1255,8 +1253,6 @@ resize_and_retry:
|
||||
pos->x_offset = info->var1.i32;
|
||||
pos->y_offset = info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
|
||||
info++, pos++;
|
||||
}
|
||||
|
||||
|
@ -878,8 +878,6 @@ retry_getglyphs:
|
||||
pos->x_offset =
|
||||
x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
|
||||
pos->y_offset = y_mult * info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
|
||||
if (isRightToLeft)
|
||||
|
@ -360,7 +360,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
|
||||
info->codepoint = gids[clusters[i].base_glyph + j];
|
||||
info->cluster = clusters[i].cluster;
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
info->var1.i32 = clusters[i].advance; // all glyphs in the cluster get the same advance
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,9 @@ struct glyf
|
||||
struct GlyphHeader
|
||||
{
|
||||
HBINT16 numberOfContours; /* If the number of contours is
|
||||
* greater than or equal to zero,
|
||||
* this is a simple glyph; if negative,
|
||||
* this is a composite glyph. */
|
||||
* greater than or equal to zero,
|
||||
* this is a simple glyph; if negative,
|
||||
* this is a composite glyph. */
|
||||
FWORD xMin; /* Minimum x for coordinate data. */
|
||||
FWORD yMin; /* Minimum y for coordinate data. */
|
||||
FWORD xMax; /* Maximum x for coordinate data. */
|
||||
@ -92,6 +92,102 @@ struct glyf
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
struct CompositeGlyphHeader
|
||||
{
|
||||
static const uint16_t ARG_1_AND_2_ARE_WORDS = 0x0001;
|
||||
static const uint16_t ARGS_ARE_XY_VALUES = 0x0002;
|
||||
static const uint16_t ROUND_XY_TO_GRID = 0x0004;
|
||||
static const uint16_t WE_HAVE_A_SCALE = 0x0008;
|
||||
static const uint16_t MORE_COMPONENTS = 0x0020;
|
||||
static const uint16_t WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
|
||||
static const uint16_t WE_HAVE_A_TWO_BY_TWO = 0x0080;
|
||||
static const uint16_t WE_HAVE_INSTRUCTIONS = 0x0100;
|
||||
static const uint16_t USE_MY_METRICS = 0x0200;
|
||||
static const uint16_t OVERLAP_COMPOUND = 0x0400;
|
||||
static const uint16_t SCALED_COMPONENT_OFFSET = 0x0800;
|
||||
static const uint16_t UNSCALED_COMPONENT_OFFSET = 0x1000;
|
||||
|
||||
HBUINT16 flags;
|
||||
HBUINT16 glyphIndex;
|
||||
|
||||
inline unsigned int get_size (void) const
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS) {
|
||||
// arg1 and 2 are int16
|
||||
size += 4;
|
||||
} else {
|
||||
// arg1 and 2 are int8
|
||||
size += 2;
|
||||
}
|
||||
if (flags & WE_HAVE_A_SCALE) {
|
||||
// One x 16 bit (scale)
|
||||
size += 2;
|
||||
} else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
|
||||
// Two x 16 bit (xscale, yscale)
|
||||
size += 4;
|
||||
} else if (flags & WE_HAVE_A_TWO_BY_TWO) {
|
||||
// Four x 16 bit (xscale, scale01, scale10, yscale)
|
||||
size += 8;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
const char *glyph_start;
|
||||
const char *glyph_end;
|
||||
const CompositeGlyphHeader *current;
|
||||
|
||||
inline bool move_to_next ()
|
||||
{
|
||||
if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
|
||||
{
|
||||
const CompositeGlyphHeader *possible =
|
||||
&StructAfter<CompositeGlyphHeader, CompositeGlyphHeader> (*current);
|
||||
if (!in_range (possible))
|
||||
return false;
|
||||
current = possible;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool in_range (const CompositeGlyphHeader *composite) const
|
||||
{
|
||||
return (const char *) composite >= glyph_start
|
||||
&& ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
|
||||
&& ((const char *) composite + composite->get_size()) <= glyph_end;
|
||||
}
|
||||
};
|
||||
|
||||
static inline bool get_iterator (const char * glyph_data,
|
||||
unsigned int length,
|
||||
CompositeGlyphHeader::Iterator *iterator /* OUT */)
|
||||
{
|
||||
if (length < GlyphHeader::static_size)
|
||||
return false; /* Empty glyph; zero extents. */
|
||||
|
||||
const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph_data, 0);
|
||||
if (glyph_header.numberOfContours < 0)
|
||||
{
|
||||
const CompositeGlyphHeader *possible =
|
||||
&StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header);
|
||||
|
||||
iterator->glyph_start = glyph_data;
|
||||
iterator->glyph_end = (const char *) glyph_data + length;
|
||||
if (!iterator->in_range (possible))
|
||||
return false;
|
||||
iterator->current = possible;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
inline void init (hb_face_t *face)
|
||||
@ -122,6 +218,23 @@ struct glyf
|
||||
hb_blob_destroy (glyf_blob);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the referenced glyph is a valid glyph and a composite glyph.
|
||||
* If true is returned a pointer to the composite glyph will be written into
|
||||
* composite.
|
||||
*/
|
||||
inline bool get_composite (hb_codepoint_t glyph,
|
||||
CompositeGlyphHeader::Iterator *composite /* OUT */) const
|
||||
{
|
||||
unsigned int start_offset, end_offset;
|
||||
if (!get_offsets (glyph, &start_offset, &end_offset))
|
||||
return false; /* glyph not found */
|
||||
|
||||
return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
|
||||
end_offset - start_offset,
|
||||
composite);
|
||||
}
|
||||
|
||||
inline bool get_offsets (hb_codepoint_t glyph,
|
||||
unsigned int *start_offset /* OUT */,
|
||||
unsigned int *end_offset /* OUT */) const
|
||||
|
@ -100,47 +100,47 @@ struct os2
|
||||
HBUINT16 version;
|
||||
|
||||
/* Version 0 */
|
||||
HBINT16 xAvgCharWidth;
|
||||
HBINT16 xAvgCharWidth;
|
||||
HBUINT16 usWeightClass;
|
||||
HBUINT16 usWidthClass;
|
||||
HBUINT16 fsType;
|
||||
HBINT16 ySubscriptXSize;
|
||||
HBINT16 ySubscriptYSize;
|
||||
HBINT16 ySubscriptXOffset;
|
||||
HBINT16 ySubscriptYOffset;
|
||||
HBINT16 ySuperscriptXSize;
|
||||
HBINT16 ySuperscriptYSize;
|
||||
HBINT16 ySuperscriptXOffset;
|
||||
HBINT16 ySuperscriptYOffset;
|
||||
HBINT16 yStrikeoutSize;
|
||||
HBINT16 yStrikeoutPosition;
|
||||
HBINT16 sFamilyClass;
|
||||
HBUINT8 panose[10];
|
||||
HBUINT32 ulUnicodeRange[4];
|
||||
HBINT16 ySubscriptXSize;
|
||||
HBINT16 ySubscriptYSize;
|
||||
HBINT16 ySubscriptXOffset;
|
||||
HBINT16 ySubscriptYOffset;
|
||||
HBINT16 ySuperscriptXSize;
|
||||
HBINT16 ySuperscriptYSize;
|
||||
HBINT16 ySuperscriptXOffset;
|
||||
HBINT16 ySuperscriptYOffset;
|
||||
HBINT16 yStrikeoutSize;
|
||||
HBINT16 yStrikeoutPosition;
|
||||
HBINT16 sFamilyClass;
|
||||
HBUINT8 panose[10];
|
||||
HBUINT32 ulUnicodeRange[4];
|
||||
Tag achVendID;
|
||||
HBUINT16 fsSelection;
|
||||
HBUINT16 usFirstCharIndex;
|
||||
HBUINT16 usLastCharIndex;
|
||||
HBINT16 sTypoAscender;
|
||||
HBINT16 sTypoDescender;
|
||||
HBINT16 sTypoLineGap;
|
||||
HBINT16 sTypoAscender;
|
||||
HBINT16 sTypoDescender;
|
||||
HBINT16 sTypoLineGap;
|
||||
HBUINT16 usWinAscent;
|
||||
HBUINT16 usWinDescent;
|
||||
|
||||
/* Version 1 */
|
||||
//HBUINT32 ulCodePageRange1;
|
||||
//HBUINT32 ulCodePageRange2;
|
||||
//HBUINT32 ulCodePageRange1;
|
||||
//HBUINT32 ulCodePageRange2;
|
||||
|
||||
/* Version 2 */
|
||||
//HBINT16 sxHeight;
|
||||
//HBINT16 sCapHeight;
|
||||
//HBUINT16 usDefaultChar;
|
||||
//HBUINT16 usBreakChar;
|
||||
//HBUINT16 usMaxContext;
|
||||
//HBINT16 sxHeight;
|
||||
//HBINT16 sCapHeight;
|
||||
//HBUINT16 usDefaultChar;
|
||||
//HBUINT16 usBreakChar;
|
||||
//HBUINT16 usMaxContext;
|
||||
|
||||
/* Version 5 */
|
||||
//HBUINT16 usLowerOpticalPointSize;
|
||||
//HBUINT16 usUpperOpticalPointSize;
|
||||
//HBUINT16 usLowerOpticalPointSize;
|
||||
//HBUINT16 usUpperOpticalPointSize;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (78);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-set.h"
|
||||
#include "hb-subset-glyf.hh"
|
||||
#include "hb-subset-plan.hh"
|
||||
|
||||
static bool
|
||||
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
|
||||
@ -70,16 +71,41 @@ _write_loca_entry (unsigned int id, unsigned int offset, bool is_short, void *lo
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_update_components (hb_subset_plan_t * plan,
|
||||
char * glyph_start,
|
||||
unsigned int length)
|
||||
|
||||
{
|
||||
OT::glyf::CompositeGlyphHeader::Iterator iterator;
|
||||
if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
|
||||
length,
|
||||
&iterator))
|
||||
{
|
||||
do
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
if (!hb_subset_plan_new_gid_for_old_id (plan,
|
||||
iterator.current->glyphIndex,
|
||||
&new_gid))
|
||||
continue;
|
||||
|
||||
((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
|
||||
} while (iterator.move_to_next());
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
_write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
|
||||
_write_glyf_and_loca_prime (hb_subset_plan_t *plan,
|
||||
const OT::glyf::accelerator_t &glyf,
|
||||
const char *glyf_data,
|
||||
hb_prealloced_array_t<hb_codepoint_t> &glyph_ids,
|
||||
bool use_short_loca,
|
||||
int glyf_prime_size,
|
||||
char *glyf_prime_data /* OUT */,
|
||||
int loca_prime_size,
|
||||
char *loca_prime_data /* OUT */)
|
||||
{
|
||||
hb_prealloced_array_t<hb_codepoint_t> &glyph_ids = plan->gids_to_retain_sorted;
|
||||
char *glyf_prime_data_next = glyf_prime_data;
|
||||
|
||||
for (unsigned int i = 0; i < glyph_ids.len; i++)
|
||||
@ -92,6 +118,7 @@ _write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
|
||||
memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
|
||||
|
||||
_write_loca_entry (i, glyf_prime_data_next - glyf_prime_data, use_short_loca, loca_prime_data);
|
||||
_update_components (plan, glyf_prime_data_next, end_offset - start_offset);
|
||||
|
||||
glyf_prime_data_next += length;
|
||||
}
|
||||
@ -104,7 +131,7 @@ _write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
|
||||
static bool
|
||||
_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
|
||||
const char *glyf_data,
|
||||
hb_prealloced_array_t<hb_codepoint_t>&glyphs_to_retain,
|
||||
hb_subset_plan_t *plan,
|
||||
bool *use_short_loca,
|
||||
hb_blob_t **glyf_prime /* OUT */,
|
||||
hb_blob_t **loca_prime /* OUT */)
|
||||
@ -112,6 +139,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
|
||||
// TODO(grieger): Sanity check writes to make sure they are in-bounds.
|
||||
// TODO(grieger): Sanity check allocation size for the new table.
|
||||
// TODO(grieger): Don't fail on bad offsets, just dump them.
|
||||
hb_prealloced_array_t<hb_codepoint_t> &glyphs_to_retain = plan->gids_to_retain_sorted;
|
||||
|
||||
unsigned int glyf_prime_size;
|
||||
unsigned int loca_prime_size;
|
||||
@ -126,7 +154,7 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
|
||||
|
||||
char *glyf_prime_data = (char *) malloc (glyf_prime_size);
|
||||
char *loca_prime_data = (char *) malloc (loca_prime_size);
|
||||
if (unlikely (!_write_glyf_and_loca_prime (glyf, glyf_data, glyphs_to_retain,
|
||||
if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
|
||||
*use_short_loca,
|
||||
glyf_prime_size, glyf_prime_data,
|
||||
loca_prime_size, loca_prime_data))) {
|
||||
@ -168,7 +196,7 @@ hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
|
||||
glyf.init(plan->source);
|
||||
bool result = _hb_subset_glyf_and_loca (glyf,
|
||||
glyf_data,
|
||||
plan->gids_to_retain_sorted,
|
||||
plan,
|
||||
use_short_loca,
|
||||
glyf_prime,
|
||||
loca_prime);
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "hb-subset-plan.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
|
||||
static int
|
||||
_hb_codepoint_t_cmp (const void *pa, const void *pb)
|
||||
@ -62,10 +63,11 @@ hb_subset_plan_new_gid_for_old_id (hb_subset_plan_t *plan,
|
||||
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.len; i++) {
|
||||
if (plan->gids_to_retain[i] == old_gid) {
|
||||
// +1: assign new gids from 1..N; 0 is special
|
||||
*new_gid = i + 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -93,6 +95,27 @@ _populate_codepoints (hb_set_t *input_codepoints,
|
||||
plan_codepoints.qsort (_hb_codepoint_t_cmp);
|
||||
}
|
||||
|
||||
static void
|
||||
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
||||
hb_codepoint_t gid,
|
||||
hb_set_t *gids_to_retain)
|
||||
{
|
||||
if (hb_set_has (gids_to_retain, gid))
|
||||
// Already visited this gid, ignore.
|
||||
return;
|
||||
|
||||
hb_set_add (gids_to_retain, gid);
|
||||
|
||||
OT::glyf::CompositeGlyphHeader::Iterator composite;
|
||||
if (glyf.get_composite (gid, &composite))
|
||||
{
|
||||
do
|
||||
{
|
||||
_add_gid_and_children (glyf, (hb_codepoint_t) composite.current->glyphIndex, gids_to_retain);
|
||||
} while (composite.move_to_next());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_populate_gids_to_retain (hb_face_t *face,
|
||||
hb_prealloced_array_t<hb_codepoint_t>& codepoints,
|
||||
@ -100,26 +123,27 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||
hb_prealloced_array_t<hb_codepoint_t>& old_gids_sorted)
|
||||
{
|
||||
OT::cmap::accelerator_t cmap;
|
||||
OT::glyf::accelerator_t glyf;
|
||||
cmap.init (face);
|
||||
glyf.init (face);
|
||||
|
||||
hb_auto_array_t<unsigned int> bad_indices;
|
||||
|
||||
old_gids.alloc (codepoints.len);
|
||||
bool has_zero = false;
|
||||
for (unsigned int i = 0; i < codepoints.len; i++) {
|
||||
for (unsigned int i = 0; i < codepoints.len; i++)
|
||||
{
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (codepoints[i], &gid)) {
|
||||
if (!cmap.get_nominal_glyph (codepoints[i], &gid))
|
||||
{
|
||||
gid = -1;
|
||||
*(bad_indices.push ()) = i;
|
||||
}
|
||||
if (gid == 0) {
|
||||
has_zero = true;
|
||||
}
|
||||
*(old_gids.push ()) = gid;
|
||||
}
|
||||
|
||||
/* Generally there shouldn't be any */
|
||||
while (bad_indices.len > 0) {
|
||||
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]);
|
||||
@ -127,19 +151,21 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||
old_gids.remove (i);
|
||||
}
|
||||
|
||||
// Populate a second glyph id array that is sorted by glyph id
|
||||
// and is gauranteed to contain 0.
|
||||
old_gids_sorted.alloc (old_gids.len + (has_zero ? 0 : 1));
|
||||
for (unsigned int i = 0; i < old_gids.len; i++) {
|
||||
*(old_gids_sorted.push ()) = old_gids[i];
|
||||
}
|
||||
if (!has_zero)
|
||||
*(old_gids_sorted.push ()) = 0;
|
||||
old_gids_sorted.qsort (_hb_codepoint_t_cmp);
|
||||
|
||||
// TODO(Q1) expand with glyphs that make up complex glyphs
|
||||
// Populate a full set of glyphs to retain by adding all referenced
|
||||
// composite glyphs.
|
||||
// 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;
|
||||
while (hb_set_next (all_gids_to_retain, &gid))
|
||||
*(old_gids_sorted.push ()) = gid;
|
||||
|
||||
glyf.fini ();
|
||||
cmap.fini ();
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,14 @@ struct hb_subset_plan_t {
|
||||
// TODO(Q1) actual map, drop this crap
|
||||
// Look at me ma, I'm a poor mans map codepoint : new gid
|
||||
// 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_prealloced_array_t<hb_codepoint_t> codepoints;
|
||||
hb_prealloced_array_t<hb_codepoint_t> gids_to_retain;
|
||||
|
||||
// This list contains the complete set of glyphs to retain and may contain
|
||||
// more glyphs then the lists above.
|
||||
hb_prealloced_array_t<hb_codepoint_t> gids_to_retain_sorted;
|
||||
|
||||
// Plan is only good for a specific source/dest so keep them with it
|
||||
|
@ -1025,8 +1025,6 @@ retry:
|
||||
pos->x_advance = x_mult * (int32_t) info->mask;
|
||||
pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
|
||||
pos->y_offset = y_mult * info->var2.i32;
|
||||
|
||||
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
}
|
||||
|
||||
if (backward)
|
||||
|
@ -12,6 +12,8 @@ lib:
|
||||
|
||||
EXTRA_DIST += CMakeLists.txt
|
||||
|
||||
EXTRA_DIST += fonts
|
||||
|
||||
if HAVE_GLIB
|
||||
AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS)
|
||||
LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
|
||||
@ -66,25 +68,6 @@ TEST_PROGS += \
|
||||
$(NULL)
|
||||
test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
|
||||
test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
|
||||
EXTRA_DIST += \
|
||||
fonts/Inconsolata-Regular.ab.ttf \
|
||||
fonts/Inconsolata-Regular.abc.ttf \
|
||||
fonts/Inconsolata-Regular.abc.widerc.ttf \
|
||||
fonts/Inconsolata-Regular.ac.ttf \
|
||||
fonts/Inconsolata-Regular.ac.widerc.ttf \
|
||||
fonts/Roboto-Regular.abc.cmap-format12-only.ttf \
|
||||
fonts/Roboto-Regular.ac.cmap-format12-only.ttf \
|
||||
fonts/Roboto-Regular.b.ttf \
|
||||
fonts/Roboto-Regular.abc.ttf \
|
||||
fonts/Roboto-Regular.ac.ttf \
|
||||
fonts/MathTestFontEmpty.otf \
|
||||
fonts/MathTestFontFull.otf \
|
||||
fonts/MathTestFontNone.otf \
|
||||
fonts/MathTestFontPartial1.otf \
|
||||
fonts/MathTestFontPartial2.otf \
|
||||
fonts/MathTestFontPartial3.otf \
|
||||
fonts/MathTestFontPartial4.otf \
|
||||
$(NULL)
|
||||
endif # HAVE_FREETYPE
|
||||
|
||||
endif # HAVE_OT
|
||||
|
BIN
test/api/fonts/Roboto-Regular.components.subset.ttf
Normal file
BIN
test/api/fonts/Roboto-Regular.components.subset.ttf
Normal file
Binary file not shown.
BIN
test/api/fonts/Roboto-Regular.components.ttf
Normal file
BIN
test/api/fonts/Roboto-Regular.components.ttf
Normal file
Binary file not shown.
@ -52,6 +52,26 @@ test_subset_glyf (void)
|
||||
hb_face_destroy (face_ac);
|
||||
}
|
||||
|
||||
static void
|
||||
test_subset_glyf_with_components (void)
|
||||
{
|
||||
hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf");
|
||||
hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.subset.ttf");
|
||||
|
||||
hb_set_t *codepoints = hb_set_create();
|
||||
hb_set_add (codepoints, 0x1fc);
|
||||
hb_face_t *face_generated_subset = hb_subset_test_create_subset (face_components, codepoints);
|
||||
hb_set_destroy (codepoints);
|
||||
|
||||
hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f'));
|
||||
hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a'));
|
||||
hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('m','a','x', 'p'));
|
||||
|
||||
hb_face_destroy (face_generated_subset);
|
||||
hb_face_destroy (face_subset);
|
||||
hb_face_destroy (face_components);
|
||||
}
|
||||
|
||||
static void
|
||||
test_subset_glyf_noop (void)
|
||||
{
|
||||
@ -79,6 +99,7 @@ main (int argc, char **argv)
|
||||
hb_test_init (&argc, &argv);
|
||||
|
||||
hb_test_add (test_subset_glyf);
|
||||
hb_test_add (test_subset_glyf_with_components);
|
||||
hb_test_add (test_subset_glyf_noop);
|
||||
|
||||
return hb_test_run();
|
||||
|
@ -37,7 +37,6 @@ static void check_num_hmetrics(hb_face_t *face, uint16_t expected_num_hmetrics)
|
||||
hb_blob_t *hmtx_blob = hb_face_reference_table (face, HB_TAG ('h','m','t','x'));
|
||||
|
||||
// TODO I sure wish I could just use the hmtx table struct!
|
||||
unsigned int hmtx_len = hb_blob_get_length(hmtx_blob);
|
||||
unsigned int hhea_len;
|
||||
uint8_t *raw_hhea = (uint8_t *) hb_blob_get_data(hhea_blob, &hhea_len);
|
||||
uint16_t num_hmetrics = (raw_hhea[hhea_len - 2] << 8) + raw_hhea[hhea_len - 1];
|
||||
|
Loading…
Reference in New Issue
Block a user