Add buffer flags

New API:

	hb_buffer_flags_t

	HB_BUFFER_FLAGS_DEFAULT
	HB_BUFFER_FLAG_BOT
	HB_BUFFER_FLAG_EOT
	HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES

	hb_buffer_set_flags()
	hb_buffer_get_flags()

We use the BOT flag to decide whether to insert dottedcircle if the
first char in the buffer is a combining mark.

The PRESERVE_DEFAULT_IGNORABLES flag prevents removal of characters like
ZWNJ/ZWJ/...
This commit is contained in:
Behdad Esfahbod 2012-11-13 14:42:35 -08:00
parent 1c7e55511a
commit 0c7df22228
6 changed files with 68 additions and 22 deletions

View File

@ -89,6 +89,7 @@ struct hb_buffer_t {
hb_unicode_funcs_t *unicode; /* Unicode functions */ hb_unicode_funcs_t *unicode; /* Unicode functions */
hb_segment_properties_t props; /* Script, language, direction */ hb_segment_properties_t props; /* Script, language, direction */
hb_buffer_flags_t flags; /* BOT / EOT / etc. */
/* Buffer contents */ /* Buffer contents */

View File

@ -153,6 +153,7 @@ hb_buffer_t::clear (void)
hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT; hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT;
props = default_props; props = default_props;
flags = HB_BUFFER_FLAGS_DEFAULT;
content_type = HB_BUFFER_CONTENT_TYPE_INVALID; content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
in_error = false; in_error = false;
@ -590,6 +591,7 @@ hb_buffer_get_empty (void)
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil), const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
_HB_BUFFER_PROPS_DEFAULT, _HB_BUFFER_PROPS_DEFAULT,
HB_BUFFER_FLAGS_DEFAULT,
HB_BUFFER_CONTENT_TYPE_INVALID, HB_BUFFER_CONTENT_TYPE_INVALID,
true, /* in_error */ true, /* in_error */
@ -724,6 +726,22 @@ hb_buffer_get_language (hb_buffer_t *buffer)
return buffer->props.language; return buffer->props.language;
} }
void
hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags)
{
if (unlikely (hb_object_is_inert (buffer)))
return;
buffer->flags = flags;
}
hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer)
{
return buffer->flags;
}
void void
hb_buffer_reset (hb_buffer_t *buffer) hb_buffer_reset (hb_buffer_t *buffer)

View File

@ -68,6 +68,12 @@ typedef enum {
HB_BUFFER_CONTENT_TYPE_GLYPHS HB_BUFFER_CONTENT_TYPE_GLYPHS
} hb_buffer_content_type_t; } hb_buffer_content_type_t;
typedef enum {
HB_BUFFER_FLAGS_DEFAULT = 0x00000000,
HB_BUFFER_FLAG_BOT = 0x00000001, /* Beginning-of-text */
HB_BUFFER_FLAG_EOT = 0x00000002, /* End-of-text */
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004
} hb_buffer_flags_t;
hb_buffer_t * hb_buffer_t *
hb_buffer_create (void); hb_buffer_create (void);
@ -129,6 +135,13 @@ hb_buffer_set_language (hb_buffer_t *buffer,
hb_language_t hb_language_t
hb_buffer_get_language (hb_buffer_t *buffer); hb_buffer_get_language (hb_buffer_t *buffer);
void
hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags);
hb_buffer_flags_t
hb_buffer_get_flags (hb_buffer_t *buffer);
/* Resets the buffer. Afterwards it's as if it was just created, /* Resets the buffer. Afterwards it's as if it was just created,
* except that it has a larger buffer allocated perhaps... */ * except that it has a larger buffer allocated perhaps... */

View File

@ -250,17 +250,18 @@ arabic_joining (hb_buffer_t *buffer)
HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action); HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
/* Check pre-context */ /* Check pre-context */
for (unsigned int i = 0; i < buffer->context_len[0]; i++) if (!(buffer->flags & HB_BUFFER_FLAG_BOT))
{ for (unsigned int i = 0; i < buffer->context_len[0]; i++)
unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i])); {
unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
if (unlikely (this_type == JOINING_TYPE_T)) if (unlikely (this_type == JOINING_TYPE_T))
continue; continue;
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
state = entry->next_state; state = entry->next_state;
break; break;
} }
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
@ -282,18 +283,19 @@ arabic_joining (hb_buffer_t *buffer)
state = entry->next_state; state = entry->next_state;
} }
for (unsigned int i = 0; i < buffer->context_len[1]; i++) if (!(buffer->flags & HB_BUFFER_FLAG_EOT))
{ for (unsigned int i = 0; i < buffer->context_len[1]; i++)
unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[0][i])); {
unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[0][i]));
if (unlikely (this_type == JOINING_TYPE_T)) if (unlikely (this_type == JOINING_TYPE_T))
continue; continue;
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != (unsigned int) -1) if (entry->prev_action != NONE && prev != (unsigned int) -1)
buffer->info[prev].arabic_shaping_action() = entry->prev_action; buffer->info[prev].arabic_shaping_action() = entry->prev_action;
break; break;
} }
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);

View File

@ -237,7 +237,7 @@ hb_set_unicode_props (hb_buffer_t *buffer)
static void static void
hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
{ {
if (buffer->context_len[0] || if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
_hb_glyph_info_get_general_category (&buffer->info[0]) != _hb_glyph_info_get_general_category (&buffer->info[0]) !=
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
return; return;
@ -509,8 +509,11 @@ hb_ot_position (hb_ot_shape_context_t *c)
/* Post-process */ /* Post-process */
static void static void
hb_ot_hide_zerowidth (hb_ot_shape_context_t *c) hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
{ {
if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
return;
hb_codepoint_t space = 0; hb_codepoint_t space = 0;
unsigned int count = c->buffer->len; unsigned int count = c->buffer->len;
@ -554,7 +557,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
hb_ot_substitute (c); hb_ot_substitute (c);
hb_ot_position (c); hb_ot_position (c);
hb_ot_hide_zerowidth (c); hb_ot_hide_default_ignorables (c);
HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1); HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1);
HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0); HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0);

View File

@ -110,6 +110,7 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
g_assert (hb_buffer_get_language (b) == NULL); g_assert (hb_buffer_get_language (b) == NULL);
g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
/* test property changes are retained */ /* test property changes are retained */
@ -127,6 +128,9 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
hb_buffer_set_language (b, hb_language_from_string ("fa", -1)); hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
/* test clear clears all properties but unicode_funcs */ /* test clear clears all properties but unicode_funcs */
@ -137,6 +141,7 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
g_assert (hb_buffer_get_language (b) == NULL); g_assert (hb_buffer_get_language (b) == NULL);
g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
/* test reset clears all properties */ /* test reset clears all properties */
@ -150,12 +155,16 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
hb_buffer_set_language (b, hb_language_from_string ("fa", -1)); hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
hb_buffer_reset (b); hb_buffer_reset (b);
g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
g_assert (hb_buffer_get_language (b) == NULL); g_assert (hb_buffer_get_language (b) == NULL);
g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
} }
static void static void