Bug 1196463 - Update harfbuzz to release 1.0.3 from upstream. r=jdaggett

This commit is contained in:
Jonathan Kew 2015-09-07 08:22:05 +01:00
parent df9bdfa193
commit c82b11c0be
27 changed files with 383 additions and 126 deletions

View File

@ -20,6 +20,8 @@ lib_LTLIBRARIES = libharfbuzz.la
HBCFLAGS =
HBLIBS =
HBNONPCLIBS =
HBDEPS =
HBSOURCES = \
hb-atomic-private.hh \
hb-blob.cc \
@ -39,6 +41,7 @@ HBSOURCES = \
hb-open-file-private.hh \
hb-open-type-private.hh \
hb-ot-cmap-table.hh \
hb-ot-glyf-table.hh \
hb-ot-head-table.hh \
hb-ot-hhea-table.hh \
hb-ot-hmtx-table.hh \
@ -93,6 +96,7 @@ HBSOURCES += \
hb-ot-shape.cc \
hb-ot-shape-complex-arabic.cc \
hb-ot-shape-complex-arabic-fallback.hh \
hb-ot-shape-complex-arabic-private.hh \
hb-ot-shape-complex-arabic-table.hh \
hb-ot-shape-complex-arabic-win1256.hh \
hb-ot-shape-complex-default.cc \
@ -132,12 +136,13 @@ endif
if HAVE_PTHREAD
HBCFLAGS += $(PTHREAD_CFLAGS)
HBLIBS += $(PTHREAD_LIBS)
HBNONPCLIBS += $(PTHREAD_LIBS)
endif
if HAVE_GLIB
HBCFLAGS += $(GLIB_CFLAGS)
HBLIBS += $(GLIB_LIBS)
HBDEPS += $(GLIB_DEPS)
HBSOURCES += hb-glib.cc
HBHEADERS += hb-glib.h
endif
@ -145,6 +150,12 @@ endif
if HAVE_FREETYPE
HBCFLAGS += $(FREETYPE_CFLAGS)
HBLIBS += $(FREETYPE_LIBS)
# XXX
# The following creates a recursive dependency on FreeType if FreeType is
# built with HarfBuzz support enabled. Newer pkg-config handles that just
# fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes. Remove
# in a year or two, or otherwise work around it...
#HBDEPS += $(FREETYPE_DEPS)
HBSOURCES += hb-ft.cc
HBHEADERS += hb-ft.h
endif
@ -152,20 +163,21 @@ endif
if HAVE_GRAPHITE2
HBCFLAGS += $(GRAPHITE2_CFLAGS)
HBLIBS += $(GRAPHITE2_LIBS)
HBDEPS += $(GRAPHITE2_DEPS)
HBSOURCES += hb-graphite2.cc
HBHEADERS += hb-graphite2.h
endif
if HAVE_UNISCRIBE
HBCFLAGS += $(UNISCRIBE_CFLAGS)
HBLIBS += $(UNISCRIBE_LIBS)
HBNONPCLIBS += $(UNISCRIBE_LIBS)
HBSOURCES += hb-uniscribe.cc
HBHEADERS += hb-uniscribe.h
endif
if HAVE_CORETEXT
HBCFLAGS += $(CORETEXT_CFLAGS)
HBLIBS += $(CORETEXT_LIBS)
HBNONPCLIBS += $(CORETEXT_LIBS)
HBSOURCES += hb-coretext.cc
HBHEADERS += hb-coretext.h
endif
@ -181,6 +193,8 @@ DIST_SUBDIRS += hb-ucdn
# Put the library together
HBLIBS += $(HBNONPCLIBS)
if OS_WIN32
export_symbols = -export-symbols harfbuzz.def
harfbuzz_def_dependency = harfbuzz.def
@ -255,6 +269,8 @@ EXTRA_DIST += \
-e 's@%exec_prefix%@$(exec_prefix)@g' \
-e 's@%libdir%@$(libdir)@g' \
-e 's@%includedir%@$(includedir)@g' \
-e 's@%libs_private%@$(HBNONPCLIBS)@g' \
-e 's@%requires_private%@$(HBDEPS)@g' \
-e 's@%VERSION%@$(VERSION)@g' \
"$<" > "$@" \
|| ($(RM) "$@"; false)
@ -269,7 +285,7 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS)
$(EGREP) '^hb_.* \(' | \
sed -e 's/ (.*//' | \
LANG=C sort; \
echo LIBRARY libharfbuzz-$(HB_VERSION_MAJOR).dll; \
echo LIBRARY libharfbuzz-0.dll; \
) >"$@"
@ ! grep -q hb_ERROR "$@" \
|| ($(RM) "$@"; false)
@ -370,7 +386,7 @@ TESTS_ENVIRONMENT = \
if HAVE_INTROSPECTION
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS = HarfBuzz-$(HB_VERSION_MAJOR).0.gir # What does the 0 mean anyway?!
INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?!
INTROSPECTION_SCANNER_ARGS = -I$(srcdir) -n hb --identifier-prefix=hb_ --warn-all
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
INTROSPECTION_SCANNER_ENV = CC="$(CC)"

View File

@ -8,4 +8,6 @@ Description: HarfBuzz text shaping library
Version: %VERSION%
Libs: -L${libdir} -lharfbuzz
Libs.private: %libs_private%
Requires.private: %requires_private%
Cflags: -I${includedir}/harfbuzz

View File

@ -201,6 +201,8 @@ struct hb_buffer_t {
HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
inline void clear_context (unsigned int side) { context_len[side] = 0; }
HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
};

View File

@ -99,7 +99,8 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
hb_buffer_serialize_flags_t flags)
{
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
*buf_consumed = 0;
for (unsigned int i = start; i < end; i++)
@ -144,6 +145,16 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
pos[i].x_advance, pos[i].y_advance);
}
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
extents.x_bearing, extents.y_bearing));
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
extents.width, extents.height));
}
*p++ = '}';
unsigned int l = p - b;
@ -172,7 +183,8 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
hb_buffer_serialize_flags_t flags)
{
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
NULL : hb_buffer_get_glyph_positions (buffer, NULL);
*buf_consumed = 0;
for (unsigned int i = start; i < end; i++)
@ -208,6 +220,13 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
}
if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
{
hb_glyph_extents_t extents;
hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
}
unsigned int l = p - b;
if (buf_size > l)
{

View File

@ -1636,7 +1636,7 @@ normalize_glyphs_cluster (hb_buffer_t *buffer,
pos[end - 1].x_advance = total_x_advance;
pos[end - 1].y_advance = total_y_advance;
hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
} else {
/* Transfer all cluster advance to the first glyph. */
pos[start].x_advance += total_x_advance;
@ -1645,7 +1645,7 @@ normalize_glyphs_cluster (hb_buffer_t *buffer,
pos[i].x_offset -= total_x_advance;
pos[i].y_offset -= total_y_advance;
}
hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
}
}
@ -1678,3 +1678,24 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
}
normalize_glyphs_cluster (buffer, start, end, backward);
}
void
hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *))
{
assert (!have_positions);
for (unsigned int i = start + 1; i < end; i++)
{
unsigned int j = i;
while (j > start && compar (&info[j - 1], &info[i]) > 0)
j--;
if (i == j)
continue;
/* Move item i to occupy place for item j, shift what's in between. */
merge_clusters (j, i + 1);
{
hb_glyph_info_t t = info[i];
memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t));
info[j] = t;
}
}
}

View File

@ -323,7 +323,8 @@ typedef enum { /*< flags >*/
HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u,
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u
} hb_buffer_serialize_flags_t;
typedef enum {

View File

@ -156,6 +156,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
/* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */
/* TODO: use upem instead of 36? */
CGFloat font_size = 36.; /* Default... */
/* No idea if the following is even a good idea. */
if (font->y_ppem)
@ -915,8 +916,8 @@ retry:
info->cluster = log_clusters[j];
info->mask = advance;
info->var1.u32 = x_offset;
info->var2.u32 = y_offset;
info->var1.i32 = x_offset;
info->var2.i32 = y_offset;
info++;
buffer->len++;
@ -1002,8 +1003,8 @@ retry:
else /* last glyph */
advance = run_advance - (positions[j].x - positions[0].x);
info->mask = advance * x_mult;
info->var1.u32 = x_offset;
info->var2.u32 = positions[j].y * y_mult;
info->var1.i32 = x_offset;
info->var2.i32 = positions[j].y * y_mult;
info++;
}
}
@ -1018,8 +1019,8 @@ retry:
else /* last glyph */
advance = run_advance - (positions[j].y - positions[0].y);
info->mask = advance * y_mult;
info->var1.u32 = positions[j].x * x_mult;
info->var2.u32 = y_offset;
info->var1.i32 = positions[j].x * x_mult;
info->var2.i32 = y_offset;
info++;
}
}
@ -1034,10 +1035,20 @@ retry:
buffer->len += num_glyphs;
}
/* Make sure all runs had the expected direction. */
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
/* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
* or if it does, it doesn't resepct it. So we get runs with wrong
* directions. As such, disable the assert... It wouldn't crash, but
* cursoring will be off...
*
* http://crbug.com/419769
*/
if (0)
{
/* Make sure all runs had the expected direction. */
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
}
buffer->clear_positions ();
@ -1048,16 +1059,16 @@ retry:
for (unsigned int i = 0; i < count; i++)
{
pos->x_advance = info->mask;
pos->x_offset = info->var1.u32;
pos->y_offset = info->var2.u32;
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
info++, pos++;
}
else
for (unsigned int i = 0; i < count; i++)
{
pos->y_advance = info->mask;
pos->x_offset = info->var1.u32;
pos->y_offset = info->var2.u32;
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
info++, pos++;
}

View File

@ -80,12 +80,13 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
/* glyph extents */
/* Note that height is negative in coordinate systems that grow up. */
typedef struct hb_glyph_extents_t
{
hb_position_t x_bearing;
hb_position_t y_bearing;
hb_position_t width;
hb_position_t height;
hb_position_t x_bearing; /* left side of glyph from origin. */
hb_position_t y_bearing; /* top side of glyph from origin. */
hb_position_t width; /* distance from left to right side. */
hb_position_t height; /* distance from top to bottom side. */
} hb_glyph_extents_t;

View File

@ -47,8 +47,9 @@
/* reference_count */
#define HB_REFERENCE_COUNT_INVALID_VALUE -1
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INVALID_VALUE)}
#define HB_REFERENCE_COUNT_INERT_VALUE -1
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)}
struct hb_reference_count_t
{
@ -58,9 +59,10 @@ struct hb_reference_count_t
inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
inline int inc (void) { return ref_count.inc (); }
inline int dec (void) { return ref_count.dec (); }
inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_INVALID_VALUE); }
inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
inline bool is_invalid (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INVALID_VALUE; }
inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
};
@ -142,7 +144,12 @@ static inline void hb_object_init (Type *obj)
template <typename Type>
static inline bool hb_object_is_inert (const Type *obj)
{
return unlikely (obj->header.ref_count.is_invalid ());
return unlikely (obj->header.ref_count.is_inert ());
}
template <typename Type>
static inline bool hb_object_is_valid (const Type *obj)
{
return likely (obj->header.ref_count.is_valid ());
}
template <typename Type>
static inline Type *hb_object_reference (Type *obj)
@ -150,6 +157,7 @@ static inline Type *hb_object_reference (Type *obj)
hb_object_trace (obj, HB_FUNC);
if (unlikely (!obj || hb_object_is_inert (obj)))
return obj;
assert (hb_object_is_valid (obj));
obj->header.ref_count.inc ();
return obj;
}
@ -159,6 +167,7 @@ static inline bool hb_object_destroy (Type *obj)
hb_object_trace (obj, HB_FUNC);
if (unlikely (!obj || hb_object_is_inert (obj)))
return false;
assert (hb_object_is_valid (obj));
if (obj->header.ref_count.dec () != 1)
return false;
@ -175,6 +184,7 @@ static inline bool hb_object_set_user_data (Type *obj,
{
if (unlikely (!obj || hb_object_is_inert (obj)))
return false;
assert (hb_object_is_valid (obj));
return obj->header.user_data.set (key, data, destroy, replace);
}
@ -184,6 +194,7 @@ static inline void *hb_object_get_user_data (Type *obj,
{
if (unlikely (!obj || hb_object_is_inert (obj)))
return NULL;
assert (hb_object_is_valid (obj));
return obj->header.user_data.get (key);
}

View File

@ -535,6 +535,20 @@ struct Supplier
template <typename Type, int Bytes> struct BEInt;
template <typename Type>
struct BEInt<Type, 1>
{
public:
inline void set (Type V)
{
v = V;
}
inline operator Type (void) const
{
return v;
}
private: uint8_t v;
};
template <typename Type>
struct BEInt<Type, 2>
{
@ -618,7 +632,7 @@ struct IntType
DEFINE_SIZE_STATIC (Size);
};
typedef uint8_t BYTE; /* 8-bit unsigned integer. */
typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */
typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */

View File

@ -31,6 +31,8 @@
#include "hb-font-private.hh"
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
@ -76,8 +78,8 @@ struct hb_ot_face_metrics_accelerator_t
if (unlikely (glyph >= this->num_metrics))
{
/* If this->num_metrics is zero, it means we don't have the metrics table
* for this direction: return one EM. Otherwise, it means that the glyph
* index is out of bound: return zero. */
* for this direction: return default advance. Otherwise, it means that the
* glyph index is out of bound: return zero. */
if (this->num_metrics)
return 0;
else
@ -91,6 +93,79 @@ struct hb_ot_face_metrics_accelerator_t
}
};
struct hb_ot_face_glyf_accelerator_t
{
bool short_offset;
unsigned int num_glyphs;
const OT::loca *loca;
const OT::glyf *glyf;
hb_blob_t *loca_blob;
hb_blob_t *glyf_blob;
unsigned int glyf_len;
inline void init (hb_face_t *face)
{
hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head));
const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob);
if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0)
{
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
hb_blob_destroy (head_blob);
return;
}
this->short_offset = 0 == head->indexToLocFormat;
hb_blob_destroy (head_blob);
this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca));
this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob);
this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf));
this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob);
this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1;
this->glyf_len = hb_blob_get_length (this->glyf_blob);
}
inline void fini (void)
{
hb_blob_destroy (this->loca_blob);
hb_blob_destroy (this->glyf_blob);
}
inline bool get_extents (hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const
{
if (unlikely (glyph >= this->num_glyphs))
return false;
unsigned int start_offset, end_offset;
if (this->short_offset)
{
start_offset = 2 * this->loca->u.shortsZ[glyph];
end_offset = 2 * this->loca->u.shortsZ[glyph + 1];
}
else
{
start_offset = this->loca->u.longsZ[glyph];
end_offset = this->loca->u.longsZ[glyph + 1];
}
if (start_offset > end_offset || end_offset > this->glyf_len)
return false;
if (end_offset - start_offset < OT::glyfGlyphHeader::static_size)
return true; /* Empty glyph; zero extents. */
const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset);
extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
return true;
}
};
struct hb_ot_face_cmap_accelerator_t
{
const OT::CmapSubtable *table;
@ -158,6 +233,7 @@ struct hb_ot_font_t
hb_ot_face_cmap_accelerator_t cmap;
hb_ot_face_metrics_accelerator_t h_metrics;
hb_ot_face_metrics_accelerator_t v_metrics;
hb_ot_face_glyf_accelerator_t glyf;
};
@ -175,6 +251,7 @@ _hb_ot_font_create (hb_font_t *font)
ot_font->cmap.init (face);
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1);
ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
return ot_font;
}
@ -276,8 +353,13 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
/* TODO */
return false;
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
bool ret = ot_font->glyf.get_extents (glyph, extents);
extents->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing);
extents->width = font->em_scale_x (extents->width);
extents->height = font->em_scale_y (extents->height);
return ret;
}
static hb_bool_t

View File

@ -138,9 +138,10 @@ struct head
* 2: Like 1 but also contains neutrals;
* -1: Only strongly right to left;
* -2: Like -1 but also contains neutrals. */
public:
SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */
SHORT glyphDataFormat; /* 0 for current format. */
public:
DEFINE_SIZE_STATIC (54);
};

View File

@ -883,6 +883,9 @@ struct EntryExitRecord
DEFINE_SIZE_STATIC (4);
};
static void
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
struct CursivePosFormat1
{
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
@ -960,20 +963,39 @@ struct CursivePosFormat1
}
/* Cross-direction adjustment */
if (c->lookup_props & LookupFlag::RightToLeft) {
pos[i].cursive_chain() = j - i;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[i].y_offset = entry_y - exit_y;
else
pos[i].x_offset = entry_x - exit_x;
} else {
pos[j].cursive_chain() = i - j;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[j].y_offset = exit_y - entry_y;
else
pos[j].x_offset = exit_x - entry_x;
/* We attach child to parent (think graph theory and rooted trees whereas
* the root stays on baseline and each node aligns itself against its
* parent.
*
* Optimize things for the case of RightToLeft, as that's most common in
* Arabinc. */
unsigned int child = i;
unsigned int parent = j;
hb_position_t x_offset = entry_x - exit_x;
hb_position_t y_offset = entry_y - exit_y;
if (!(c->lookup_props & LookupFlag::RightToLeft))
{
unsigned int k = child;
child = parent;
parent = k;
x_offset = -x_offset;
y_offset = -y_offset;
}
/* If child was already connected to someone else, walk through its old
* chain and reverse the link direction, such that the whole tree of its
* previous connection now attaches to new parent. Watch out for case
* where new parent is on the path from old chain...
*/
reverse_cursive_minor_offset (pos, child, c->direction, parent);
pos[child].cursive_chain() = parent - child;
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
pos[child].y_offset = y_offset;
else
pos[child].x_offset = x_offset;
buffer->idx = j;
return TRACE_RETURN (true);
}
@ -1482,6 +1504,30 @@ struct GPOS : GSUBGPOS
};
static void
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
{
unsigned int j = pos[i].cursive_chain();
if (likely (!j))
return;
j += i;
pos[i].cursive_chain() = 0;
/* Stop if we see new parent in the chain. */
if (j == new_parent)
return;
reverse_cursive_minor_offset (pos, j, direction, new_parent);
if (HB_DIRECTION_IS_HORIZONTAL (direction))
pos[j].y_offset = -pos[i].y_offset;
else
pos[j].x_offset = -pos[i].x_offset;
pos[j].cursive_chain() = i - j;
}
static void
fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
{
@ -1568,8 +1614,11 @@ template <typename context_t>
const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
const PosLookup &l = gpos.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
c->set_lookup (l);
unsigned int saved_lookup_index = c->lookup_index;
c->set_lookup_index (lookup_index);
c->set_lookup_props (l.get_props ());
bool ret = l.dispatch (c);
c->set_lookup_index (saved_lookup_index);
c->set_lookup_props (saved_lookup_props);
return ret;
}

View File

@ -1311,8 +1311,11 @@ template <typename context_t>
const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
c->set_lookup (l);
unsigned int saved_lookup_index = c->lookup_index;
c->set_lookup_index (lookup_index);
c->set_lookup_props (l.get_props ());
bool ret = l.dispatch (c);
c->set_lookup_index (saved_lookup_index);
c->set_lookup_props (saved_lookup_props);
return ret;
}

View File

@ -266,7 +266,8 @@ struct hb_add_coverage_context_t
#define TRACE_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
"idx %d gid %u lookup %d", \
c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index);
struct hb_apply_context_t
{
@ -481,6 +482,7 @@ struct hb_apply_context_t
const GDEF &gdef;
bool has_glyph_classes;
skipping_iterator_t iter_input, iter_context;
unsigned int lookup_index;
unsigned int debug_depth;
@ -499,12 +501,13 @@ struct hb_apply_context_t
has_glyph_classes (gdef.has_glyph_classes ()),
iter_input (),
iter_context (),
lookup_index ((unsigned int) -1),
debug_depth (0) {}
inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
inline void set_lookup (const Lookup &l) { set_lookup_props (l.get_props ()); }
inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
inline void set_lookup_props (unsigned int lookup_props_)
{
lookup_props = lookup_props_;

View File

@ -959,7 +959,7 @@ apply_string (OT::hb_apply_context_t *c,
if (unlikely (!buffer->len || !c->lookup_mask))
return;
c->set_lookup (lookup);
c->set_lookup_props (lookup.get_props ());
if (likely (!lookup.is_reverse ()))
{
@ -1010,7 +1010,20 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const stage_map_t *stage = &stages[table_index][stage_index];
for (; i < stage->last_lookup; i++)
{
#if 0
char buf[4096];
hb_buffer_serialize_glyphs (buffer, 0, buffer->len,
buf, sizeof (buf), NULL,
font,
HB_BUFFER_SERIALIZE_FORMAT_TEXT,
Proxy::table_index == 0 ?
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS :
HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
printf ("buf: [%s]\n", buf);
#endif
unsigned int lookup_index = lookups[table_index][i].index;
c.set_lookup_index (lookup_index);
c.set_lookup_mask (lookups[table_index][i].mask);
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
apply_string<Proxy> (&c,

View File

@ -75,9 +75,9 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
if (!num_glyphs)
return NULL;
/* Bubble-sort!
/* Bubble-sort or something equally good!
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
hb_stable_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]);
OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs);
OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
@ -126,7 +126,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
num_first_glyphs++;
}
hb_bubble_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]);
hb_stable_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]);
/* Now that the first-glyphs are sorted, walk again, populate ligatures. */
for (unsigned int i = 0; i < num_first_glyphs; i++)

View File

@ -205,11 +205,11 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
buffer->next_glyph ();
if (!is_zero_width_char (font, u))
{
buffer->merge_out_clusters (start, end + 1);
hb_glyph_info_t *info = buffer->out_info;
hb_glyph_info_t tone = info[end];
memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
info[start] = tone;
buffer->merge_out_clusters (start, end + 1);
}
}
else

View File

@ -1012,7 +1012,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
info[i].syllable() = i - start;
/* Sit tight, rock 'n roll! */
hb_bubble_sort (info + start, end - start, compare_indic_order);
hb_stable_sort (info + start, end - start, compare_indic_order);
/* Find base again */
base = end;
for (unsigned int i = start; i < end; i++)
@ -1025,7 +1025,11 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* around like crazy. In old-spec mode, we move halants around, so in
* that case merge all clusters after base. Otherwise, check the sort
* order and merge as needed.
* For pre-base stuff, we handle cluster issues in final reordering. */
* For pre-base stuff, we handle cluster issues in final reordering.
*
* We could use buffer->sort() for this, if there was no special
* reordering of pre-base stuff happening later...
*/
if (indic_plan->is_old_spec || end - base > 127)
buffer->merge_clusters (base, end);
else
@ -1404,12 +1408,17 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (info[i - 1].indic_position () == POS_PRE_M)
{
unsigned int old_pos = i - 1;
if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
base--;
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
info[new_pos] = tmp;
if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
base--;
/* Note: this merge_clusters() is intentionally *after* the reordering.
* Indic matra reordering is special and tricky... */
buffer->merge_clusters (new_pos, MIN (end, base + 1));
new_pos--;
}
} else {
@ -1562,12 +1571,12 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
reph_move:
{
buffer->merge_clusters (start, new_reph_pos + 1);
/* Move */
buffer->merge_clusters (start, new_reph_pos + 1);
hb_glyph_info_t reph = info[start];
memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
info[new_reph_pos] = reph;
if (start < base && base <= new_reph_pos)
base--;
}
@ -1640,10 +1649,12 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
{
unsigned int old_pos = i;
buffer->merge_clusters (new_pos, old_pos + 1);
hb_glyph_info_t tmp = info[old_pos];
memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
info[new_pos] = tmp;
if (new_pos <= base && base < old_pos)
base++;
}

View File

@ -391,9 +391,8 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
}
}
buffer->merge_clusters (start, end);
/* Sit tight, rock 'n roll! */
hb_bubble_sort (info + start, end - start, compare_myanmar_order);
buffer->sort (start, end, compare_myanmar_order);
}
static void

View File

@ -353,7 +353,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
{
/* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
* previous cluster. */
if (start)
if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
buffer->merge_out_clusters (start - 1, end);
}
}

View File

@ -238,14 +238,6 @@ enum syllable_type_t {
#include "hb-ot-shape-complex-use-machine.hh"
static inline void
set_use_properties (hb_glyph_info_t &info)
{
hb_codepoint_t u = info.codepoint;
info.use_category() = hb_use_get_categories (u);
}
static void
setup_masks_use (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
@ -444,10 +436,10 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
if (info[i].use_category() == USE_H)
i--;
buffer->merge_clusters (start, i + 1);
hb_glyph_info_t t = info[start];
memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
info[i] = t;
buffer->merge_clusters (start, i + 1);
break;
}
@ -472,10 +464,10 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
j < i)
{
buffer->merge_clusters (j, i + 1);
hb_glyph_info_t t = info[i];
memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0]));
info[j] = t;
buffer->merge_clusters (j, i + 1);
}
}
}

View File

@ -344,15 +344,13 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
break;
/* We are going to do a bubble-sort. Only do this if the
* sequence is short. Doing it on long sequences can result
* in an O(n^2) DoS. */
/* We are going to do a O(n^2). Only do this if the sequence is short. */
if (end - i > 10) {
i = end;
continue;
}
hb_bubble_sort (buffer->info + i, end - i, compare_combining_class);
buffer->sort (i, end, compare_combining_class);
i = end;
}

View File

@ -302,15 +302,16 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
{
if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
{
buffer->reverse_range (base, i);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
buffer->merge_clusters (base, i);
buffer->reverse_range (base, i);
base = i;
}
}
buffer->reverse_range (base, count);
if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
buffer->merge_clusters (base, count);
buffer->reverse_range (base, count);
buffer->reverse ();
@ -513,6 +514,8 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
info[i].codepoint = info[i].glyph_index();
buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
}
static inline void

View File

@ -855,42 +855,34 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
template <typename T, typename T2> static inline void
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
{
if (unlikely (!len))
return;
unsigned int k = len - 1;
do {
unsigned int new_k = 0;
for (unsigned int j = 0; j < k; j++)
if (compar (&array[j], &array[j+1]) > 0)
{
{
T t;
t = array[j];
array[j] = array[j + 1];
array[j + 1] = t;
}
if (array2)
{
T2 t;
t = array2[j];
array2[j] = array2[j + 1];
array2[j + 1] = t;
}
new_k = j;
}
k = new_k;
} while (k);
for (unsigned int i = 1; i < len; i++)
{
unsigned int j = i;
while (j && compar (&array[j - 1], &array[i]) > 0)
j--;
if (i == j)
continue;
/* Move item i to occupy place for item j, shift what's in between. */
{
T t = array[i];
memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
array[j] = t;
}
if (array2)
{
T2 t = array2[i];
memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
array2[j] = t;
}
}
}
template <typename T> static inline void
hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
{
hb_bubble_sort (array, len, compar, (int *) NULL);
hb_stable_sort (array, len, compar, (int *) NULL);
}
static inline hb_bool_t

View File

@ -486,14 +486,16 @@ struct hb_uniscribe_shaper_font_data_t {
LOGFONTW log_font;
HFONT hfont;
SCRIPT_CACHE script_cache;
double x_mult, y_mult; /* From LOGFONT space to HB space. */
};
static bool
populate_log_font (LOGFONTW *lf,
hb_font_t *font)
hb_font_t *font,
unsigned int font_size)
{
memset (lf, 0, sizeof (*lf));
lf->lfHeight = -font->y_scale;
lf->lfHeight = -font_size;
lf->lfCharSet = DEFAULT_CHARSET;
hb_face_t *face = font->face;
@ -513,9 +515,19 @@ _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
if (unlikely (!data))
return NULL;
int font_size = font->face->get_upem (); /* Default... */
/* No idea if the following is even a good idea. */
if (font->y_ppem)
font_size = font->y_ppem;
if (font_size < 0)
font_size = -font_size;
data->x_mult = (double) font->x_scale / font_size;
data->y_mult = (double) font->y_scale / font_size;
data->hdc = GetDC (NULL);
if (unlikely (!populate_log_font (&data->log_font, font))) {
if (unlikely (!populate_log_font (&data->log_font, font, font_size))) {
DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
_hb_uniscribe_shaper_font_data_destroy (data);
return NULL;
@ -994,21 +1006,22 @@ retry:
/* The rest is crap. Let's store position info there for now. */
info->mask = advances[i];
info->var1.u32 = offsets[i].du;
info->var2.u32 = offsets[i].dv;
info->var1.i32 = offsets[i].du;
info->var2.i32 = offsets[i].dv;
}
/* Set glyph positions */
buffer->clear_positions ();
double x_mult = font_data->x_mult, y_mult = font_data->y_mult;
for (unsigned int i = 0; i < glyphs_len; i++)
{
hb_glyph_info_t *info = &buffer->info[i];
hb_glyph_position_t *pos = &buffer->pos[i];
/* TODO vertical */
pos->x_advance = info->mask;
pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
pos->y_offset = info->var2.u32;
pos->x_advance = x_mult * info->mask;
pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
pos->y_offset = y_mult * info->var2.i32;
}
if (backward)

View File

@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 0
#define HB_VERSION_MICRO 1
#define HB_VERSION_MICRO 3
#define HB_VERSION_STRING "1.0.1"
#define HB_VERSION_STRING "1.0.3"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \