Evas font-engine: Use binary search for finding index in text props.

I finally got around to verifying it and the list is assured to be monotonic
(direction depends on bidi direction).

SVN revision: 59903
This commit is contained in:
Tom Hacohen 2011-06-02 15:36:50 +00:00
parent 1b7ff0248e
commit 85cf792f24
2 changed files with 73 additions and 47 deletions

View File

@ -65,29 +65,81 @@ evas_common_text_props_content_unref(Evas_Text_Props *props)
} }
} }
EAPI Eina_Bool /* Returns the index of the logical char in the props. */
evas_common_text_props_can_split(Evas_Text_Props *props, int _cutoff) EAPI int
evas_common_text_props_index_find(Evas_Text_Props *props, int _cutoff)
{ {
#ifdef OT_SUPPORT #ifdef OT_SUPPORT
Evas_Font_OT_Info *itr; Evas_Font_OT_Info *ot_info;
size_t i; int min = 0;
itr = props->info->ot + props->start; int max = props->len - 1;
int mid;
_cutoff += props->text_offset; _cutoff += props->text_offset;
/* FIXME: can I binary search? I don't think this is always sorted */ ot_info = props->info->ot + props->start;
for (i = 0 ; i < props->len ; i++, itr++) if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{ {
if (itr->source_cluster == (size_t) _cutoff) /* Monotonic in a descending order */
do
{ {
return EINA_TRUE; mid = (min + max) / 2;
if (_cutoff > (int) ot_info[mid].source_cluster)
max = mid - 1;
else if (_cutoff < (int) ot_info[mid].source_cluster)
min = mid + 1;
else
break;
} }
while (min <= max);
}
else
{
/* Monotonic in an ascending order */
do
{
mid = (min + max) / 2;
if (_cutoff < (int) ot_info[mid].source_cluster)
max = mid - 1;
else if (_cutoff > (int) ot_info[mid].source_cluster)
min = mid + 1;
else
break;
}
while (min <= max);
} }
/* We didn't find the cutoff position. */ /* If we didn't find, abort */
ERR("Couldn't find the cutoff position. Is it inside a cluster?"); if (min > max)
return EINA_FALSE; return -1;
ot_info += mid;
if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
/* Walk to the last one of the same cluster */
for ( ; mid < (int) props->len ; mid++, ot_info++)
{
if (ot_info->source_cluster != (size_t) _cutoff)
break;
}
mid = props->len - mid;
}
else
{
/* Walk to the last one of the same cluster */
for ( ; mid >= 0 ; mid--, ot_info--)
{
if (ot_info->source_cluster != (size_t) _cutoff)
break;
}
mid++;
}
return mid;
#else #else
return EINA_TRUE; return _cutoff;
props = 0; _cutoff = 0; (void) props;
#endif #endif
} }
@ -102,41 +154,15 @@ evas_common_text_props_split(Evas_Text_Props *base,
/* Translate text cutoff pos to string object cutoff point */ /* Translate text cutoff pos to string object cutoff point */
#ifdef OT_SUPPORT #ifdef OT_SUPPORT
cutoff = 0; _cutoff = evas_common_text_props_index_find(base, _cutoff);
if (_cutoff > 0)
{ {
Evas_Font_OT_Info *itr; cutoff = (size_t) _cutoff;
size_t i;
itr = base->info->ot + base->start;
_cutoff += base->text_offset;
/* Must do a linear search because this is not always sorted. */
for (i = 0 ; i < base->len ; i++, itr++)
{
if (itr->source_cluster == (size_t) _cutoff)
{
if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
/* Walk to the last one of the same cluster */
for ( ; i < base->len ; i++, itr++)
{
if (itr->source_cluster != (size_t) _cutoff)
break;
}
cutoff = base->len - i;
}
else
{
cutoff = i;
}
break;
}
}
} }
else
/* If we didn't find a reasonable cut location, return. */
if (cutoff == 0)
{ {
ERR("Couldn't find the cutoff position (%d). Is it inside a cluster?", _cutoff); ERR("Couldn't find the cutoff position. Is it inside a cluster?");
return; return;
} }
#else #else

View File

@ -71,8 +71,8 @@ evas_common_text_props_content_ref(Evas_Text_Props *props);
void void
evas_common_text_props_content_unref(Evas_Text_Props *props); evas_common_text_props_content_unref(Evas_Text_Props *props);
EAPI Eina_Bool EAPI int
evas_common_text_props_can_split(Evas_Text_Props *props, int _cutoff); evas_common_text_props_index_find(Evas_Text_Props *props, int _cutoff);
EAPI void EAPI void
evas_common_text_props_split(Evas_Text_Props *base, Evas_Text_Props *ext, evas_common_text_props_split(Evas_Text_Props *base, Evas_Text_Props *ext,