Merge branch 'master' into bitops

This commit is contained in:
Behdad Esfahbod 2018-02-18 10:45:33 -08:00 committed by GitHub
commit fe8f40a418
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 255 additions and 116 deletions

29
TODO
View File

@ -1,24 +1,14 @@
General fixes: General fixes:
============= =============
- AAT 'morx' implementation.
- Return "safe-to-break" bit from shaping.
- Implement 'rand' feature. - Implement 'rand' feature.
- mask propagation? (when ligation, "or" the masks).
API issues: API issues:
=========== ===========
- API to accept a list of languages? - 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()? - Remove hb_ot_shape_glyphs_closure()?
@ -39,7 +29,7 @@ API additions
- Add query / enumeration API for aalt-like features? - 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 - Add segmentation API
@ -50,20 +40,3 @@ hb-view / hb-shape enhancements:
=============================== ===============================
- Add --width, --height, --auto-size, --ink-box, --align, etc? - 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

View File

@ -344,8 +344,7 @@ struct hb_buffer_t {
inline void inline void
unsafe_to_break_all (void) unsafe_to_break_all (void)
{ {
for (unsigned int i = 0; i < len; i++) unsafe_to_break_impl (0, len);
info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
} }
inline void inline void
safe_to_break_all (void) safe_to_break_all (void)

View File

@ -1244,8 +1244,6 @@ resize_and_retry:
pos->x_offset = info->var1.i32; pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32; pos->y_offset = info->var2.i32;
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
info++, pos++; info++, pos++;
} }
else else
@ -1255,8 +1253,6 @@ resize_and_retry:
pos->x_offset = info->var1.i32; pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32; pos->y_offset = info->var2.i32;
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
info++, pos++; info++, pos++;
} }

View File

@ -878,8 +878,6 @@ retry_getglyphs:
pos->x_offset = pos->x_offset =
x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32); x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
pos->y_offset = y_mult * info->var2.i32; pos->y_offset = y_mult * info->var2.i32;
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
} }
if (isRightToLeft) if (isRightToLeft)

View File

@ -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]; hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
info->codepoint = gids[clusters[i].base_glyph + j]; info->codepoint = gids[clusters[i].base_glyph + j];
info->cluster = clusters[i].cluster; 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 info->var1.i32 = clusters[i].advance; // all glyphs in the cluster get the same advance
} }
} }

View File

@ -81,9 +81,9 @@ struct glyf
struct GlyphHeader struct GlyphHeader
{ {
HBINT16 numberOfContours; /* If the number of contours is HBINT16 numberOfContours; /* If the number of contours is
* greater than or equal to zero, * greater than or equal to zero,
* this is a simple glyph; if negative, * this is a simple glyph; if negative,
* this is a composite glyph. */ * this is a composite glyph. */
FWORD xMin; /* Minimum x for coordinate data. */ FWORD xMin; /* Minimum x for coordinate data. */
FWORD yMin; /* Minimum y for coordinate data. */ FWORD yMin; /* Minimum y for coordinate data. */
FWORD xMax; /* Maximum x for coordinate data. */ FWORD xMax; /* Maximum x for coordinate data. */
@ -92,6 +92,102 @@ struct glyf
DEFINE_SIZE_STATIC (10); 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 struct accelerator_t
{ {
inline void init (hb_face_t *face) inline void init (hb_face_t *face)
@ -122,6 +218,23 @@ struct glyf
hb_blob_destroy (glyf_blob); 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, inline bool get_offsets (hb_codepoint_t glyph,
unsigned int *start_offset /* OUT */, unsigned int *start_offset /* OUT */,
unsigned int *end_offset /* OUT */) const unsigned int *end_offset /* OUT */) const

View File

@ -100,47 +100,47 @@ struct os2
HBUINT16 version; HBUINT16 version;
/* Version 0 */ /* Version 0 */
HBINT16 xAvgCharWidth; HBINT16 xAvgCharWidth;
HBUINT16 usWeightClass; HBUINT16 usWeightClass;
HBUINT16 usWidthClass; HBUINT16 usWidthClass;
HBUINT16 fsType; HBUINT16 fsType;
HBINT16 ySubscriptXSize; HBINT16 ySubscriptXSize;
HBINT16 ySubscriptYSize; HBINT16 ySubscriptYSize;
HBINT16 ySubscriptXOffset; HBINT16 ySubscriptXOffset;
HBINT16 ySubscriptYOffset; HBINT16 ySubscriptYOffset;
HBINT16 ySuperscriptXSize; HBINT16 ySuperscriptXSize;
HBINT16 ySuperscriptYSize; HBINT16 ySuperscriptYSize;
HBINT16 ySuperscriptXOffset; HBINT16 ySuperscriptXOffset;
HBINT16 ySuperscriptYOffset; HBINT16 ySuperscriptYOffset;
HBINT16 yStrikeoutSize; HBINT16 yStrikeoutSize;
HBINT16 yStrikeoutPosition; HBINT16 yStrikeoutPosition;
HBINT16 sFamilyClass; HBINT16 sFamilyClass;
HBUINT8 panose[10]; HBUINT8 panose[10];
HBUINT32 ulUnicodeRange[4]; HBUINT32 ulUnicodeRange[4];
Tag achVendID; Tag achVendID;
HBUINT16 fsSelection; HBUINT16 fsSelection;
HBUINT16 usFirstCharIndex; HBUINT16 usFirstCharIndex;
HBUINT16 usLastCharIndex; HBUINT16 usLastCharIndex;
HBINT16 sTypoAscender; HBINT16 sTypoAscender;
HBINT16 sTypoDescender; HBINT16 sTypoDescender;
HBINT16 sTypoLineGap; HBINT16 sTypoLineGap;
HBUINT16 usWinAscent; HBUINT16 usWinAscent;
HBUINT16 usWinDescent; HBUINT16 usWinDescent;
/* Version 1 */ /* Version 1 */
//HBUINT32 ulCodePageRange1; //HBUINT32 ulCodePageRange1;
//HBUINT32 ulCodePageRange2; //HBUINT32 ulCodePageRange2;
/* Version 2 */ /* Version 2 */
//HBINT16 sxHeight; //HBINT16 sxHeight;
//HBINT16 sCapHeight; //HBINT16 sCapHeight;
//HBUINT16 usDefaultChar; //HBUINT16 usDefaultChar;
//HBUINT16 usBreakChar; //HBUINT16 usBreakChar;
//HBUINT16 usMaxContext; //HBUINT16 usMaxContext;
/* Version 5 */ /* Version 5 */
//HBUINT16 usLowerOpticalPointSize; //HBUINT16 usLowerOpticalPointSize;
//HBUINT16 usUpperOpticalPointSize; //HBUINT16 usUpperOpticalPointSize;
public: public:
DEFINE_SIZE_STATIC (78); DEFINE_SIZE_STATIC (78);

View File

@ -28,6 +28,7 @@
#include "hb-ot-glyf-table.hh" #include "hb-ot-glyf-table.hh"
#include "hb-set.h" #include "hb-set.h"
#include "hb-subset-glyf.hh" #include "hb-subset-glyf.hh"
#include "hb-subset-plan.hh"
static bool static bool
_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf, _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 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, const char *glyf_data,
hb_prealloced_array_t<hb_codepoint_t> &glyph_ids,
bool use_short_loca, bool use_short_loca,
int glyf_prime_size, int glyf_prime_size,
char *glyf_prime_data /* OUT */, char *glyf_prime_data /* OUT */,
int loca_prime_size, int loca_prime_size,
char *loca_prime_data /* OUT */) 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; char *glyf_prime_data_next = glyf_prime_data;
for (unsigned int i = 0; i < glyph_ids.len; i++) 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); 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); _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; glyf_prime_data_next += length;
} }
@ -104,7 +131,7 @@ _write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
static bool static bool
_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf, _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
const char *glyf_data, const char *glyf_data,
hb_prealloced_array_t<hb_codepoint_t>&glyphs_to_retain, hb_subset_plan_t *plan,
bool *use_short_loca, bool *use_short_loca,
hb_blob_t **glyf_prime /* OUT */, hb_blob_t **glyf_prime /* OUT */,
hb_blob_t **loca_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 writes to make sure they are in-bounds.
// TODO(grieger): Sanity check allocation size for the new table. // TODO(grieger): Sanity check allocation size for the new table.
// TODO(grieger): Don't fail on bad offsets, just dump them. // 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 glyf_prime_size;
unsigned int loca_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 *glyf_prime_data = (char *) malloc (glyf_prime_size);
char *loca_prime_data = (char *) malloc (loca_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, *use_short_loca,
glyf_prime_size, glyf_prime_data, glyf_prime_size, glyf_prime_data,
loca_prime_size, loca_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); glyf.init(plan->source);
bool result = _hb_subset_glyf_and_loca (glyf, bool result = _hb_subset_glyf_and_loca (glyf,
glyf_data, glyf_data,
plan->gids_to_retain_sorted, plan,
use_short_loca, use_short_loca,
glyf_prime, glyf_prime,
loca_prime); loca_prime);

View File

@ -28,6 +28,7 @@
#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"
static int static int
_hb_codepoint_t_cmp (const void *pa, const void *pb) _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) hb_codepoint_t *new_gid)
{ {
// the index in old_gids is the new gid; only up to codepoints.len are valid // 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++) { for (unsigned int i = 0; i < plan->gids_to_retain_sorted.len; i++)
if (plan->gids_to_retain[i] == old_gid) { {
// +1: assign new gids from 1..N; 0 is special if (plan->gids_to_retain_sorted[i] == old_gid)
*new_gid = i + 1; {
*new_gid = i;
return true; return true;
} }
} }
@ -93,6 +95,27 @@ _populate_codepoints (hb_set_t *input_codepoints,
plan_codepoints.qsort (_hb_codepoint_t_cmp); 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 static void
_populate_gids_to_retain (hb_face_t *face, _populate_gids_to_retain (hb_face_t *face,
hb_prealloced_array_t<hb_codepoint_t>& codepoints, 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) hb_prealloced_array_t<hb_codepoint_t>& old_gids_sorted)
{ {
OT::cmap::accelerator_t cmap; OT::cmap::accelerator_t cmap;
OT::glyf::accelerator_t glyf;
cmap.init (face); cmap.init (face);
glyf.init (face);
hb_auto_array_t<unsigned int> bad_indices; hb_auto_array_t<unsigned int> bad_indices;
old_gids.alloc (codepoints.len); 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; hb_codepoint_t gid;
if (!cmap.get_nominal_glyph (codepoints[i], &gid)) { if (!cmap.get_nominal_glyph (codepoints[i], &gid))
{
gid = -1; gid = -1;
*(bad_indices.push ()) = i; *(bad_indices.push ()) = i;
} }
if (gid == 0) {
has_zero = true;
}
*(old_gids.push ()) = gid; *(old_gids.push ()) = gid;
} }
/* Generally there shouldn't be any */ /* 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]; unsigned int i = bad_indices[bad_indices.len - 1];
bad_indices.pop (); bad_indices.pop ();
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", codepoints[i]); 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); old_gids.remove (i);
} }
// Populate a second glyph id array that is sorted by glyph id // Populate a full set of glyphs to retain by adding all referenced
// and is gauranteed to contain 0. // composite glyphs.
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
// 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;
while (hb_set_next (all_gids_to_retain, &gid))
*(old_gids_sorted.push ()) = gid;
glyf.fini ();
cmap.fini (); cmap.fini ();
} }

View File

@ -38,8 +38,14 @@ struct hb_subset_plan_t {
// TODO(Q1) actual map, drop this crap // TODO(Q1) actual map, drop this crap
// Look at me ma, I'm a poor mans map codepoint : new gid // Look at me ma, I'm a poor mans map codepoint : new gid
// codepoints is sorted and aligned with gids_to_retain. // 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> codepoints;
hb_prealloced_array_t<hb_codepoint_t> gids_to_retain; 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; 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 // Plan is only good for a specific source/dest so keep them with it

View File

@ -1025,8 +1025,6 @@ retry:
pos->x_advance = x_mult * (int32_t) info->mask; pos->x_advance = x_mult * (int32_t) info->mask;
pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32); pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
pos->y_offset = y_mult * info->var2.i32; pos->y_offset = y_mult * info->var2.i32;
info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
} }
if (backward) if (backward)

View File

@ -12,6 +12,8 @@ lib:
EXTRA_DIST += CMakeLists.txt EXTRA_DIST += CMakeLists.txt
EXTRA_DIST += fonts
if HAVE_GLIB if HAVE_GLIB
AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS) AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS)
LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS) LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
@ -66,25 +68,6 @@ TEST_PROGS += \
$(NULL) $(NULL)
test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS) test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) 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_FREETYPE
endif # HAVE_OT endif # HAVE_OT

Binary file not shown.

Binary file not shown.

View File

@ -52,6 +52,26 @@ test_subset_glyf (void)
hb_face_destroy (face_ac); 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 static void
test_subset_glyf_noop (void) test_subset_glyf_noop (void)
{ {
@ -79,6 +99,7 @@ main (int argc, char **argv)
hb_test_init (&argc, &argv); hb_test_init (&argc, &argv);
hb_test_add (test_subset_glyf); hb_test_add (test_subset_glyf);
hb_test_add (test_subset_glyf_with_components);
hb_test_add (test_subset_glyf_noop); hb_test_add (test_subset_glyf_noop);
return hb_test_run(); return hb_test_run();

View File

@ -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')); 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! // 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; unsigned int hhea_len;
uint8_t *raw_hhea = (uint8_t *) hb_blob_get_data(hhea_blob, &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]; uint16_t num_hmetrics = (raw_hhea[hhea_len - 2] << 8) + raw_hhea[hhea_len - 1];