Merge pull request #745 from googlefonts/master
Interface for hb_subset, skeleton for the hb-subset cli, and basic testing rigging.
diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index 1ea8318..74f9fdb 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -614,8 +614,7 @@
hb_face_t *face_) :
machine (machine_),
buffer (buffer_),
- num_glyphs (face_->get_num_glyphs ()),
- last_zero (0) {}
+ num_glyphs (face_->get_num_glyphs ()) {}
template <typename context_t>
inline void drive (context_t *c)
@@ -629,9 +628,6 @@
bool last_was_dont_advance = false;
for (buffer->idx = 0;;)
{
- if (!state)
- last_zero = buffer->idx;
-
unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
0 /* End of text */;
@@ -639,6 +635,30 @@
if (unlikely (!entry))
break;
+ /* Unsafe-to-break before this if not in state 0, as things might
+ * go differently if we start from state 0 here. */
+ if (state && buffer->idx)
+ {
+ /* Special-case easy cases: if starting here at state 0 is not
+ * actionable, and leads to the same next state, then it's safe.
+ * Let's hope... Maybe disable the conditional later, if proves
+ * insufficient. */
+ const Entry<EntryData> *start_entry = machine.get_entryZ (0, klass);
+ if (start_entry->newState != entry->newState ||
+ (start_entry->flags & context_t::DontAdvance) != (entry->flags & context_t::DontAdvance) ||
+ c->is_actionable (this, entry) ||
+ c->is_actionable (this, start_entry))
+ buffer->unsafe_to_break (buffer->idx - 1, buffer->idx + 1);
+ }
+
+ /* Unsafe-to-break if end-of-text would kick in here. */
+ if (buffer->idx + 2 <= buffer->len)
+ {
+ const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
+ if (c->is_actionable (this, end_entry))
+ buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
+ }
+
if (unlikely (!c->transition (this, entry)))
break;
@@ -665,7 +685,6 @@
const StateTable<EntryData> &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
- unsigned int last_zero;
};
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index ffe4d03..4e75dd3 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -58,9 +58,13 @@
inline driver_context_t (const RearrangementSubtable *table) :
ret (false),
- start (0), end (0),
- last_zero_before_start (0) {}
+ start (0), end (0) {}
+ inline bool is_actionable (StateTableDriver<void> *driver,
+ const Entry<void> *entry)
+ {
+ return (entry->flags & Verb) && start < end;
+ }
inline bool transition (StateTableDriver<void> *driver,
const Entry<void> *entry)
{
@@ -68,10 +72,7 @@
unsigned int flags = entry->flags;
if (flags & MarkFirst)
- {
start = buffer->idx;
- last_zero_before_start = driver->last_zero;
- }
if (flags & MarkLast)
end = MIN (buffer->idx + 1, buffer->len);
@@ -110,7 +111,7 @@
if (end - start >= l + r)
{
- buffer->unsafe_to_break (last_zero_before_start, MIN (buffer->idx + 1, buffer->len));
+ buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
buffer->merge_clusters (start, end);
hb_glyph_info_t *info = buffer->info;
@@ -147,7 +148,6 @@
private:
unsigned int start;
unsigned int end;
- unsigned int last_zero_before_start;
};
inline bool apply (hb_aat_apply_context_t *c) const
@@ -198,44 +198,59 @@
inline driver_context_t (const ContextualSubtable *table) :
ret (false),
+ mark_set (false),
mark (0),
- last_zero_before_mark (0),
subs (table+table->substitutionTables) {}
+ inline bool is_actionable (StateTableDriver<EntryData> *driver,
+ const Entry<EntryData> *entry)
+ {
+ hb_buffer_t *buffer = driver->buffer;
+
+ if (buffer->idx == buffer->len && !mark_set)
+ return false;
+
+ return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
+ }
inline bool transition (StateTableDriver<EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
- if (entry->data.markIndex != 0xFFFF && mark < buffer->len)
+ /* Looks like CoreText applies neither mark nor current substitution for
+ * end-of-text if mark was not explicitly set. */
+ if (buffer->idx == buffer->len && !mark_set)
+ return true;
+
+ if (entry->data.markIndex != 0xFFFF)
{
const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
hb_glyph_info_t *info = buffer->info;
const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs);
if (replacement)
{
- buffer->unsafe_to_break (last_zero_before_mark, MIN (buffer->idx + 1, buffer->len));
+ buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
info[mark].codepoint = *replacement;
ret = true;
}
}
- if (entry->data.currentIndex != 0xFFFF && buffer->idx < buffer->len)
+ if (entry->data.currentIndex != 0xFFFF)
{
+ unsigned int idx = MIN (buffer->idx, buffer->len - 1);
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
hb_glyph_info_t *info = buffer->info;
- const GlyphID *replacement = lookup.get_value (info[buffer->idx].codepoint, driver->num_glyphs);
+ const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs);
if (replacement)
{
- buffer->unsafe_to_break (driver->last_zero, MIN (buffer->idx + 1, buffer->len));
- info[buffer->idx].codepoint = *replacement;
+ info[idx].codepoint = *replacement;
ret = true;
}
}
if (entry->flags & SetMark)
{
+ mark_set = true;
mark = buffer->idx;
- last_zero_before_mark = driver->last_zero;
}
return true;
@@ -244,8 +259,8 @@
public:
bool ret;
private:
+ bool mark_set;
unsigned int mark;
- unsigned int last_zero_before_mark;
const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
};
@@ -335,6 +350,11 @@
ligature (table+table->ligature),
match_length (0) {}
+ inline bool is_actionable (StateTableDriver<EntryData> *driver,
+ const Entry<EntryData> *entry)
+ {
+ return !!(entry->flags & PerformAction);
+ }
inline bool transition (StateTableDriver<EntryData> *driver,
const Entry<EntryData> *entry)
{
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 7ead43b..7fb000d 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1933,7 +1933,7 @@
result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH;
if (buf_info->cluster != ref_info->cluster)
result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH;
- if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED))
+ if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) & (ref_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED))
result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH;
if (contains && ref_info->codepoint == dottedcircle_glyph)
result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT;
diff --git a/test/shaping/data/text-rendering-tests/DISABLED b/test/shaping/data/text-rendering-tests/DISABLED
index 1439d43..5117455 100644
--- a/test/shaping/data/text-rendering-tests/DISABLED
+++ b/test/shaping/data/text-rendering-tests/DISABLED
@@ -23,6 +23,7 @@
tests/MORX-20.tests
tests/MORX-21.tests
tests/MORX-22.tests
+tests/MORX-23.tests
# Rounding differences
tests/SHARAN-1.tests
diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources
index c28487f..b12f173 100644
--- a/test/shaping/data/text-rendering-tests/Makefile.sources
+++ b/test/shaping/data/text-rendering-tests/Makefile.sources
@@ -43,10 +43,11 @@
tests/MORX-17.tests \
tests/MORX-18.tests \
tests/MORX-19.tests \
+ tests/MORX-1.tests \
tests/MORX-20.tests \
tests/MORX-21.tests \
tests/MORX-22.tests \
- tests/MORX-1.tests \
+ tests/MORX-23.tests \
tests/MORX-2.tests \
tests/MORX-3.tests \
tests/MORX-4.tests \
diff --git a/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentythree.ttf b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentythree.ttf
new file mode 100644
index 0000000..df34912
--- /dev/null
+++ b/test/shaping/data/text-rendering-tests/fonts/TestMORXTwentythree.ttf
Binary files differ
diff --git a/test/shaping/data/text-rendering-tests/tests/MORX-23.tests b/test/shaping/data/text-rendering-tests/tests/MORX-23.tests
new file mode 100644
index 0000000..9575a80
--- /dev/null
+++ b/test/shaping/data/text-rendering-tests/tests/MORX-23.tests
@@ -0,0 +1 @@
+../fonts/TestMORXTwentythree.ttf:--font-size=1000 --ned --remove-default-ignorables --font-funcs=ft:U+0041,U+0042,U+0043,U+0044,U+0045:[E|E@556,0|E@1112,0|E@1668,0|E@2224,0]