Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion make/lib/Awt2dLibraries.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ else

HARFBUZZ_DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing
HARFBUZZ_DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
maybe-uninitialized class-memaccess
maybe-uninitialized class-memaccess unused-result
HARFBUZZ_DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \
tautological-constant-out-of-range-compare int-to-pointer-cast \
undef missing-field-initializers range-loop-analysis
Expand Down
2 changes: 1 addition & 1 deletion src/java.desktop/share/legal/harfbuzz.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Harfbuzz v2.7.2
## Harfbuzz v2.8

### Harfbuzz License

Expand Down
115 changes: 80 additions & 35 deletions src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ struct StateTable
const Entry<Extra> &get_entry (int state, unsigned int klass) const
{
if (unlikely (klass >= nClasses))
klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS;
klass = StateTable::CLASS_OUT_OF_BOUNDS;

const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ;
Expand Down Expand Up @@ -576,7 +576,7 @@ struct StateTable
if (unlikely (stop > states))
return_trace (false);
for (const HBUSHORT *p = states; stop < p; p--)
num_entries = hb_max (num_entries, *(p - 1) + 1);
num_entries = hb_max (num_entries, *(p - 1) + 1u);
state_neg = min_state;
}
}
Expand All @@ -597,7 +597,7 @@ struct StateTable
if (unlikely (stop < states))
return_trace (false);
for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
num_entries = hb_max (num_entries, *p + 1);
num_entries = hb_max (num_entries, *p + 1u);
state_pos = max_state + 1;
}
}
Expand Down Expand Up @@ -729,7 +729,10 @@ struct ExtendedTypes
template <typename Types, typename EntryData>
struct StateTableDriver
{
StateTableDriver (const StateTable<Types, EntryData> &machine_,
using StateTableT = StateTable<Types, EntryData>;
using EntryT = Entry<EntryData>;

StateTableDriver (const StateTableT &machine_,
hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
Expand All @@ -742,59 +745,101 @@ struct StateTableDriver
if (!c->in_place)
buffer->clear_output ();

int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
int state = StateTableT::STATE_START_OF_TEXT;
for (buffer->idx = 0; buffer->successful;)
{
unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
(unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
(unsigned) StateTableT::CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const Entry<EntryData> &entry = machine.get_entry (state, klass);
const EntryT &entry = machine.get_entry (state, klass);
const int next_state = machine.new_state (entry.newState);

/* Unsafe-to-break before this if not in state 0, as things might
* go differently if we start from state 0 here.
/* Conditions under which it's guaranteed safe-to-break before current glyph:
*
* Ugh. The indexing here is ugly... */
if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
{
/* If there's no action and we're just epsilon-transitioning to state 0,
* safe to break. */
if (c->is_actionable (this, entry) ||
!(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
entry.flags == context_t::DontAdvance))
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 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_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
if (c->is_actionable (this, end_entry))
buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
}
* 1. There was no action in this transition; and
*
* 2. If we break before current glyph, the results will be the same. That
* is guaranteed if:
*
* 2a. We were already in start-of-text state; or
*
* 2b. We are epsilon-transitioning to start-of-text state; or
*
* 2c. Starting from start-of-text state seeing current glyph:
*
* 2c'. There won't be any actions; and
*
* 2c". We would end up in the same state that we were going to end up
* in now, including whether epsilon-transitioning.
*
* and
*
* 3. If we break before current glyph, there won't be any end-of-text action
* after previous glyph.
*
* This triples the transitions we need to look up, but is worth returning
* granular unsafe-to-break results. See eg.:
*
* https://github.com/harfbuzz/harfbuzz/issues/2860
*/
const EntryT *wouldbe_entry;
bool safe_to_break =
/* 1. */
!c->is_actionable (this, entry)
&&
/* 2. */
(
/* 2a. */
state == StateTableT::STATE_START_OF_TEXT
||
/* 2b. */
(
(entry.flags & context_t::DontAdvance) &&
next_state == StateTableT::STATE_START_OF_TEXT
)
||
/* 2c. */
(
wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
,
/* 2c'. */
!c->is_actionable (this, *wouldbe_entry)
&&
/* 2c". */
(
next_state == machine.new_state (wouldbe_entry->newState)
&&
(entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
)
)
)
&&
/* 3. */
!c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
;

if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);

c->transition (this, entry);

state = machine.new_state (entry.newState);
state = next_state;
DEBUG_MSG (APPLY, nullptr, "s%d", state);

if (buffer->idx == buffer->len)
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
break;

if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
buffer->next_glyph ();
(void) buffer->next_glyph ();
}

if (!c->in_place)
{
for (; buffer->successful && buffer->idx < buffer->len;)
buffer->next_glyph ();
buffer->swap_buffers ();
}
}

public:
const StateTable<Types, EntryData> &machine;
const StateTableT &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,9 @@ struct ContextualSubtable
const EntryData &data = entries[i].data;

if (data.markIndex != 0xFFFF)
num_lookups = hb_max (num_lookups, 1 + data.markIndex);
num_lookups = hb_max (num_lookups, 1u + data.markIndex);
if (data.currentIndex != 0xFFFF)
num_lookups = hb_max (num_lookups, 1 + data.currentIndex);
num_lookups = hb_max (num_lookups, 1u + data.currentIndex);
}

return_trace (substitutionTables.sanitize (c, this, num_lookups));
Expand Down Expand Up @@ -499,7 +499,7 @@ struct LigatureSubtable
}

DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;

if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
action = *actionData;
Expand All @@ -525,25 +525,25 @@ struct LigatureSubtable
hb_codepoint_t lig = ligatureData;

DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
buffer->replace_glyph (lig);
if (unlikely (!buffer->replace_glyph (lig))) return;

unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
/* Now go and delete all subsequent components. */
while (match_length - 1u > cursor)
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
buffer->replace_glyph (DELETED_GLYPH);
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
}

buffer->move_to (lig_end);
if (unlikely (!buffer->move_to (lig_end))) return;
buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
}

actionData++;
}
while (!(action & LigActionLast));
buffer->move_to (end);
if (unlikely (!buffer->move_to (end))) return;
}
}

Expand Down Expand Up @@ -733,17 +733,16 @@ struct InsertionSubtable
bool before = flags & MarkedInsertBefore;

unsigned int end = buffer->out_len;
buffer->move_to (mark);
if (unlikely (!buffer->move_to (mark))) return;

if (buffer->idx < buffer->len && !before)
buffer->copy_glyph ();
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++)
buffer->output_glyph (glyphs[i]);
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();

buffer->move_to (end + count);
if (unlikely (!buffer->move_to (end + count))) return;

buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
}
Expand All @@ -764,10 +763,9 @@ struct InsertionSubtable
unsigned int end = buffer->out_len;

if (buffer->idx < buffer->len && !before)
buffer->copy_glyph ();
if (unlikely (!buffer->copy_glyph ())) return;
/* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++)
buffer->output_glyph (glyphs[i]);
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
if (buffer->idx < buffer->len && !before)
buffer->skip_glyph ();

Expand All @@ -786,7 +784,7 @@ struct InsertionSubtable
*
* https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
*/
buffer->move_to ((flags & DontAdvance) ? end : end + count);
if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return;
}
}

Expand Down
Loading