Evas object: Add paragraph_direciton APIs

Summary:
It adds evas_object_paragraph_direction_set, get APIs.
The APIs set or get paragraph direction to/from the given object.
It changes BiDi calculations and affect the direction and aligning of text.
It doesn't have any effect to text without Fribidi library.

The default paragraph direction is EVAS_BIDI_DIRECTION_INHERIT.
If dir is EVAS_BIDI_DIRECTION_INHERIT, paragraph direction is changed
according to smart parent object. If there is no smart parent object,
paragraph direction works as EVAS_BIDI_DIRECTION_NEUTRAL.

@feature

Test Plan:
Test cases included to the following files.
- evas_test_textblock.c
- evas_test_text.c
- evas_test_object_smart.c

Run "make check".

Reviewers: woohyun, raster, herdsman, tasn

Subscribers: c, raster, cedric

Differential Revision: https://phab.enlightenment.org/D1690
This commit is contained in:
Youngbok Shin 2015-11-19 11:37:07 +00:00 committed by Tom Hacohen
parent 618558f8ec
commit a9b4be11e1
19 changed files with 775 additions and 16 deletions

View File

@ -2121,6 +2121,7 @@ tests_evas_evas_suite_SOURCES = \
tests/evas/evas_suite.c \
tests/evas/evas_test_init.c \
tests/evas/evas_test_object.c \
tests/evas/evas_test_object_smart.c \
tests/evas/evas_test_textblock.c \
tests/evas/evas_test_text.c \
tests/evas/evas_test_callbacks.c \

View File

@ -2138,6 +2138,7 @@ class Edje.Object (Evas.Smart_Clipped, Efl.File)
Eo.Base.constructor;
Eo.Base.destructor;
Eo.Base.dbg_info_get;
Evas.Object.paragraph_direction.set;
Evas.Object_Smart.hide;
Evas.Object_Smart.calculate;
Evas.Object_Smart.show;

View File

@ -389,4 +389,15 @@ edje_object_file_get(const Edje_Object *obj, const char **file, const char **gro
eo_do((Edje_Object *)obj, efl_file_get(file, group));
}
EOLIAN static void
_edje_object_evas_object_paragraph_direction_set(Eo *obj, Edje *ed, Evas_BiDi_Direction dir)
{
eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(dir));
/* Make it dirty to recalculate edje.
It needs to move text objects according to new paragraph direction */
ed->dirty = EINA_TRUE;
eo_do(obj, evas_obj_smart_need_recalculate_set(1));
}
#include "edje_object.eo.c"

View File

@ -976,6 +976,19 @@ abstract Evas.Object (Eo.Base, Evas.Common_Interface, Efl.Gfx.Base, Efl.Gfx.Stac
dispmode: Evas.Display_Mode; [[Display mode hint.]]
}
}
@property paragraph_direction {
[[This handles text paragraph direction of the given object.
Even if the given object is not textblock or text, its smart child objects
can inherit the paragraph direction from the given object.
The default paragraph direction is @Evas.BiDi_Direction.inherit.]]
set {
}
get {
}
values {
dir: Evas.BiDi_Direction; [[Paragraph direction for the given object.]]
}
}
clipees_has @const {
[[Test if any object is clipped by $obj.

View File

@ -2013,5 +2013,17 @@ _evas_object_smart_type_check_ptr(const Eo *eo_obj EINA_UNUSED, Evas_Object_Prot
return EINA_FALSE;
}
EOLIAN static void
_evas_object_paragraph_direction_set(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj EINA_UNUSED, Evas_BiDi_Direction dir EINA_UNUSED)
{
return;
}
EOLIAN static Evas_BiDi_Direction
_evas_object_paragraph_direction_get(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj EINA_UNUSED)
{
return EVAS_BIDI_DIRECTION_NEUTRAL;
}
#include "canvas/evas_object.eo.c"

View File

@ -35,6 +35,8 @@ struct _Evas_Smart_Data
unsigned char recalculate_cycle;
Evas_BiDi_Direction paragraph_direction : 2;
Eina_Bool inherit_paragraph_direction : 1;
Eina_Bool deletions_waiting : 1;
Eina_Bool need_recalculate : 1;
Eina_Bool update_boundingbox_needed : 1;
@ -83,6 +85,8 @@ static void evas_object_smart_render_post(Evas_Object *eo_obj,
static unsigned int evas_object_smart_id_get(Evas_Object *eo_obj);
static unsigned int evas_object_smart_visual_id_get(Evas_Object *eo_obj);
static void *evas_object_smart_engine_data_get(Evas_Object *eo_obj);
static void _evas_object_smart_paragraph_direction_set_internal(Eo *eo_obj,
Evas_BiDi_Direction dir);
static const Evas_Object_Func object_func =
{
@ -209,6 +213,7 @@ _evas_object_smart_member_add(Eo *smart_obj, Evas_Smart_Data *o, Evas_Object *eo
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Object_Protected_Data *smart = eo_data_scope_get(smart_obj, EVAS_OBJECT_CLASS);
Evas_Smart_Data *member_o;
if (obj->delete_me)
{
@ -257,6 +262,19 @@ _evas_object_smart_member_add(Eo *smart_obj, Evas_Smart_Data *o, Evas_Object *eo
evas_object_smart_member_cache_invalidate(eo_obj, EINA_TRUE, EINA_TRUE,
EINA_TRUE);
obj->restack = 1;
if (obj->is_smart)
{
member_o = eo_data_scope_get(eo_obj, EVAS_OBJECT_SMART_CLASS);
if ((member_o->inherit_paragraph_direction) &&
(member_o->paragraph_direction != o->paragraph_direction))
{
member_o->paragraph_direction = o->paragraph_direction;
_evas_object_smart_paragraph_direction_set_internal(eo_obj, o->paragraph_direction);
}
}
evas_object_change(eo_obj, obj);
evas_object_mapped_clip_across_mark(eo_obj, obj);
if (smart->smart.smart && smart->smart.smart->smart_class->member_add)
@ -282,6 +300,7 @@ EOLIAN static void
_evas_object_smart_member_del(Eo *smart_obj, Evas_Smart_Data *_pd EINA_UNUSED, Evas_Object *eo_obj)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Smart_Data *member_o;
if (!obj->smart.parent) return;
@ -304,6 +323,18 @@ _evas_object_smart_member_del(Eo *smart_obj, Evas_Smart_Data *_pd EINA_UNUSED, E
}
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
if (obj->is_smart)
{
member_o = eo_data_scope_get(eo_obj, EVAS_OBJECT_SMART_CLASS);
if ((member_o->inherit_paragraph_direction) &&
(member_o->paragraph_direction != EVAS_BIDI_DIRECTION_NEUTRAL))
{
member_o->paragraph_direction = EVAS_BIDI_DIRECTION_NEUTRAL;
_evas_object_smart_paragraph_direction_set_internal(eo_obj, EVAS_BIDI_DIRECTION_NEUTRAL);
}
}
evas_object_inject(eo_obj, obj, obj->layer->evas->evas);
obj->restack = 1;
evas_object_change(eo_obj, obj);
@ -551,6 +582,7 @@ _evas_object_smart_eo_base_constructor(Eo *eo_obj, Evas_Smart_Data *class_data E
smart = class_data;
smart->object = eo_obj;
smart->inherit_paragraph_direction = EINA_TRUE;
eo_obj = eo_do_super_ret(eo_obj, MY_CLASS, eo_obj, eo_constructor());
evas_object_smart_init(eo_obj);
@ -1469,4 +1501,78 @@ _evas_object_smart_class_destructor(Eo_Class *klass EINA_UNUSED)
eina_hash_free(_evas_smart_class_names_hash_table);
}
static void
_evas_object_smart_paragraph_direction_set_internal(Eo *eo_obj,
Evas_BiDi_Direction dir)
{
Evas_Object_Protected_Data *o;
Evas_Smart_Data *member_o;
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), o)
{
evas_object_change(o->object, o);
if (o->is_smart)
{
member_o = eo_data_scope_get(o->object, EVAS_OBJECT_SMART_CLASS);
if ((member_o->inherit_paragraph_direction) &&
(member_o->paragraph_direction != dir))
{
member_o->paragraph_direction = dir;
_evas_object_smart_paragraph_direction_set_internal(o->object, dir);
}
}
}
}
EOLIAN static void
_evas_object_smart_evas_object_paragraph_direction_set(Eo *eo_obj, Evas_Smart_Data *o, Evas_BiDi_Direction dir)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Smart_Data *parent;
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
if ((!(o->inherit_paragraph_direction) && (o->paragraph_direction == dir)) ||
(o->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
return;
if (dir == EVAS_BIDI_DIRECTION_INHERIT)
{
o->inherit_paragraph_direction = EINA_TRUE;
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
{
parent = eo_data_scope_get(obj->smart.parent, EVAS_OBJECT_SMART_CLASS);
if (parent)
parent_dir = parent->paragraph_direction;
}
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
evas_object_change(eo_obj, obj);
}
}
else
{
o->inherit_paragraph_direction = EINA_FALSE;
o->paragraph_direction = dir;
evas_object_change(eo_obj, obj);
}
_evas_object_smart_paragraph_direction_set_internal(eo_obj, o->paragraph_direction);
}
EOLIAN static Evas_BiDi_Direction
_evas_object_smart_evas_object_paragraph_direction_get(Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o)
{
return o->paragraph_direction;
}
#include "canvas/evas_object_smart.eo.c"

View File

@ -300,5 +300,7 @@ class Evas.Object_Smart (Evas.Object, Evas.Signal_Interface)
Evas.Object.smart_type_check_ptr;
Evas.Object.smart_type_check;
Evas.Object.smart_data.get;
Evas.Object.paragraph_direction.set;
Evas.Object.paragraph_direction.get;
}
}

View File

@ -68,6 +68,9 @@ struct _Evas_Text_Data
float max_ascent, max_descent;
Evas_BiDi_Direction bidi_dir : 2;
Evas_BiDi_Direction paragraph_direction : 2;
Eina_Bool inherit_paragraph_direction : 1;
Eina_Bool changed_paragraph_direction : 1;
Eina_Bool changed : 1;
Eina_Bool has_filter : 1;
};
@ -696,7 +699,8 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t
o->cur.text == text &&
obj->cur->scale == obj->prev->scale &&
((o->last_computed.advance <= obj->cur->geometry.w && !o->last_computed.ellipsis) ||
o->last_computed.w == obj->cur->geometry.w))
(o->last_computed.w == obj->cur->geometry.w)) &&
!o->changed_paragraph_direction)
return;
o->last_computed.ellipsis = EINA_FALSE;
@ -717,7 +721,28 @@ _evas_object_text_layout(Evas_Object *eo_obj, Evas_Text_Data *o, Eina_Unicode *t
}
evas_bidi_paragraph_props_unref(o->bidi_par_props);
if (text)
o->bidi_par_props = evas_bidi_paragraph_props_get(text, len, segment_idxs);
{
Evas_BiDi_Direction par_dir;
EvasBiDiParType bidi_par_type;
par_dir = o->paragraph_direction;
switch (par_dir)
{
case EVAS_BIDI_DIRECTION_LTR:
bidi_par_type = EVAS_BIDI_PARAGRAPH_LTR;
break;
case EVAS_BIDI_DIRECTION_RTL:
bidi_par_type = EVAS_BIDI_PARAGRAPH_RTL;
break;
case EVAS_BIDI_DIRECTION_NEUTRAL:
default:
bidi_par_type = EVAS_BIDI_PARAGRAPH_NEUTRAL;
break;
}
o->bidi_par_props = evas_bidi_paragraph_props_get(text, len, segment_idxs, bidi_par_type);
}
if (o->bidi_par_props)
o->bidi_dir = EVAS_BIDI_PAR_TYPE_TO_DIRECTION(o->bidi_par_props->direction);
@ -1056,8 +1081,33 @@ _evas_text_efl_text_text_get(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
}
EOLIAN static Evas_BiDi_Direction
_evas_text_direction_get(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
_evas_text_direction_get(Eo *eo_obj, Evas_Text_Data *o)
{
#ifdef BIDI_SUPPORT
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if (o->inherit_paragraph_direction)
{
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
o->changed_paragraph_direction = EINA_TRUE;
}
}
if (o->changed_paragraph_direction)
{
_evas_object_text_recalc(eo_obj, o->cur.text);
evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
eo_obj, obj);
}
#endif
return o->bidi_dir;
}
@ -1537,6 +1587,7 @@ evas_object_text_init(Evas_Object *eo_obj)
o->prev = o->cur;
#ifdef BIDI_SUPPORT
o->bidi_par_props = evas_bidi_paragraph_props_new();
o->inherit_paragraph_direction = EINA_TRUE;
#endif
eo_do(eo_obj, evas_filter_constructor());
@ -1925,12 +1976,30 @@ evas_object_text_render_pre(Evas_Object *eo_obj,
obj->cur->clipper,
obj->cur->clipper->private_data);
}
#ifdef BIDI_SUPPORT
if (o->inherit_paragraph_direction)
{
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
o->changed_paragraph_direction = EINA_TRUE;
}
}
#endif
/* If object size changed and ellipsis is set */
if (((o->cur.ellipsis >= 0.0 ||
o->cur.ellipsis != o->prev.ellipsis) &&
((obj->cur->geometry.w != o->last_computed.w) ||
(obj->cur->geometry.h != o->last_computed.h))) ||
(obj->cur->scale != obj->prev->scale))
(obj->cur->scale != obj->prev->scale) ||
(o->changed_paragraph_direction))
{
_evas_object_text_recalc(eo_obj, o->cur.text);
evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
@ -2199,6 +2268,9 @@ _evas_object_text_recalc(Evas_Object *eo_obj, Eina_Unicode *text)
}
o->last_computed.w = obj->cur->geometry.w;
o->last_computed.h = obj->cur->geometry.h;
#ifdef BIDI_SUPPORT
o->changed_paragraph_direction = EINA_FALSE;
#endif
}
EAPI void
@ -2247,4 +2319,50 @@ _evas_text_efl_gfx_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, c
eo_do_super(obj, MY_CLASS, efl_gfx_filter_program_set(code, name));
}
EOLIAN static void
_evas_text_evas_object_paragraph_direction_set(Eo *eo_obj, Evas_Text_Data *o, Evas_BiDi_Direction dir)
{
#ifdef BIDI_SUPPORT
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if ((!(o->inherit_paragraph_direction) && (o->paragraph_direction == dir)) ||
(o->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
return;
if (dir == EVAS_BIDI_DIRECTION_INHERIT)
{
o->inherit_paragraph_direction = EINA_TRUE;
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
o->changed_paragraph_direction = EINA_TRUE;
evas_object_change(eo_obj, obj);
}
}
else
{
o->inherit_paragraph_direction = EINA_FALSE;
o->paragraph_direction = dir;
o->changed_paragraph_direction = EINA_TRUE;
evas_object_change(eo_obj, obj);
}
#else
(void) eo_obj;
(void) o;
(void) dir;
#endif
}
EOLIAN static Evas_BiDi_Direction
_evas_text_evas_object_paragraph_direction_get(Eo *eo_obj EINA_UNUSED,
Evas_Text_Data *o)
{
return o->paragraph_direction;
}
#include "canvas/evas_text.eo.c"

View File

@ -507,6 +507,7 @@ struct _Evas_Object_Textblock
void *engine_data;
const char *repch;
const char *bidi_delimiters;
Evas_BiDi_Direction paragraph_direction : 2;
struct {
int w, h, oneline_h;
Eina_Bool valid : 1;
@ -518,6 +519,8 @@ struct _Evas_Object_Textblock
Eina_Bool format_changed : 1;
Eina_Bool have_ellipsis : 1;
Eina_Bool legacy_newline : 1;
Eina_Bool inherit_paragraph_direction : 1;
Eina_Bool changed_paragraph_direction : 1;
};
struct _Evas_Textblock_Selection_Iterator
@ -2882,15 +2885,34 @@ _layout_update_bidi_props(const Evas_Textblock_Data *o,
{
const Eina_Unicode *text;
int *segment_idxs = NULL;
Evas_BiDi_Direction par_dir;
EvasBiDiParType bidi_par_type;
text = eina_ustrbuf_string_get(par->text_node->unicode);
if (o->bidi_delimiters)
segment_idxs = evas_bidi_segment_idxs_get(text, o->bidi_delimiters);
par_dir = o->paragraph_direction;
switch (par_dir)
{
case EVAS_BIDI_DIRECTION_LTR:
bidi_par_type = EVAS_BIDI_PARAGRAPH_LTR;
break;
case EVAS_BIDI_DIRECTION_RTL:
bidi_par_type = EVAS_BIDI_PARAGRAPH_RTL;
break;
case EVAS_BIDI_DIRECTION_NEUTRAL:
default:
bidi_par_type = EVAS_BIDI_PARAGRAPH_NEUTRAL;
break;
}
evas_bidi_paragraph_props_unref(par->bidi_props);
par->bidi_props = evas_bidi_paragraph_props_get(text,
eina_ustrbuf_length_get(par->text_node->unicode),
segment_idxs);
segment_idxs, bidi_par_type);
par->direction = EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(par->bidi_props) ?
EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
par->is_bidi = !!par->bidi_props;
@ -5801,6 +5823,9 @@ _relayout(const Evas_Object *eo_obj)
o->content_changed = 0;
o->format_changed = EINA_FALSE;
o->redraw = 1;
#ifdef BIDI_SUPPORT
o->changed_paragraph_direction = EINA_FALSE;
#endif
}
/*
@ -11502,6 +11527,9 @@ evas_object_textblock_init(Evas_Object *eo_obj)
evas_object_textblock_text_markup_set(eo_obj, "");
o->legacy_newline = EINA_TRUE;
#ifdef BIDI_SUPPORT
o->inherit_paragraph_direction = EINA_TRUE;
#endif
}
EOLIAN static void
@ -12045,12 +12073,30 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
}
static void
evas_object_textblock_coords_recalc(Evas_Object *eo_obj EINA_UNUSED,
evas_object_textblock_coords_recalc(Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj,
void *type_private_data)
{
Evas_Textblock_Data *o = type_private_data;
#ifdef BIDI_SUPPORT
if (o->inherit_paragraph_direction)
{
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
{
parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
}
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
o->changed_paragraph_direction = EINA_TRUE;
}
}
#endif
if (
// width changed thus we may have to re-wrap or change centering etc.
(obj->cur->geometry.w != o->last_w) ||
@ -12068,10 +12114,18 @@ evas_object_textblock_coords_recalc(Evas_Object *eo_obj EINA_UNUSED,
(o->content_changed) ||
// if format changed (eg styles) we need to re-format/match tags etc.
(o->format_changed) ||
(o->obstacle_changed)
(o->obstacle_changed) ||
(o->changed_paragraph_direction)
)
{
LYDBG("ZZ: invalidate 2 %p ## %i != %i || %3.3f || %i && %i != %i | %i %i\n", eo_obj, obj->cur->geometry.w, o->last_w, o->valign, o->have_ellipsis, obj->cur->geometry.h, o->last_h, o->content_changed, o->format_changed);
LYDBG("ZZ: invalidate 2 %p ## %i != %i || %3.3f || %i && %i != %i | %i %i || %d\n", eo_obj, obj->cur->geometry.w, o->last_w, o->valign, o->have_ellipsis, obj->cur->geometry.h, o->last_h, o->content_changed, o->format_changed, o->changed_paragraph_direction);
if (o->changed_paragraph_direction)
{
_evas_textblock_invalidate_all(o);
_evas_textblock_changed(o, eo_obj);
}
o->formatted.valid = 0;
o->changed = 1;
}
@ -12291,6 +12345,56 @@ _evas_object_textblock_rehint(Evas_Object *eo_obj)
_evas_textblock_changed(o, eo_obj);
}
EOLIAN static void
_evas_textblock_evas_object_paragraph_direction_set(Eo *eo_obj,
Evas_Textblock_Data *o,
Evas_BiDi_Direction dir)
{
#ifdef BIDI_SUPPORT
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if ((!(o->inherit_paragraph_direction) && (o->paragraph_direction == dir)) ||
(o->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
return;
if (dir == EVAS_BIDI_DIRECTION_INHERIT)
{
o->inherit_paragraph_direction = EINA_TRUE;
Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
if (obj->smart.parent)
parent_dir = evas_object_paragraph_direction_get(obj->smart.parent);
if (parent_dir != o->paragraph_direction)
{
o->paragraph_direction = parent_dir;
o->changed_paragraph_direction = EINA_TRUE;
_evas_textblock_invalidate_all(o);
_evas_textblock_changed(o, eo_obj);
}
}
else
{
o->inherit_paragraph_direction = EINA_FALSE;
o->paragraph_direction = dir;
o->changed_paragraph_direction = EINA_TRUE;
_evas_textblock_invalidate_all(o);
_evas_textblock_changed(o, eo_obj);
}
#else
(void) eo_obj;
(void) o;
(void) dir;
#endif
}
EOLIAN static Evas_BiDi_Direction
_evas_textblock_evas_object_paragraph_direction_get(Eo *eo_obj EINA_UNUSED,
Evas_Textblock_Data *o)
{
return o->paragraph_direction;
}
/**
* @}
*/

View File

@ -264,5 +264,7 @@ class Evas.Text (Evas.Object, Efl.Text, Efl.Text_Properties, Evas.Filter)
Evas.Filter.input_alpha;
Evas.Filter.input_render;
Evas.Filter.dirty;
Evas.Object.paragraph_direction.set;
Evas.Object.paragraph_direction.get;
}
}

View File

@ -325,5 +325,7 @@ class Evas.Textblock (Evas.Object)
Eo.Base.constructor;
Eo.Base.destructor;
Eo.Base.dbg_info_get;
Evas.Object.paragraph_direction.set;
Evas.Object.paragraph_direction.get;
}
}

View File

@ -72,7 +72,8 @@ enum Evas.BiDi_Direction {
natural = 0,
neutral = 0,
ltr,
rtl
rtl,
inherit
}
enum Evas.Text_Style_Type {

View File

@ -222,11 +222,12 @@ evas_bidi_segment_idxs_get(const Eina_Unicode *str, const char *delim)
* @param ustr The string to update according to.
* @param len The length of the string
* @param segment_idxs A -1 terminated array of points to start a new bidi analysis at (used for section high level bidi overrides). - NULL means none.
* @param base_bidi The base BiDi direction of paragraph.
* @return returns allocated paragraph props on success, NULL otherwise.
*/
Evas_BiDi_Paragraph_Props *
evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len,
int *segment_idxs)
int *segment_idxs, EvasBiDiParType base_bidi)
{
Evas_BiDi_Paragraph_Props *bidi_props = NULL;
EvasBiDiCharType *char_types = NULL;
@ -237,8 +238,9 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len,
if (!eina_ustr)
return NULL;
if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */
/* No need to handle bidi */
if (!evas_bidi_is_rtl_str(eina_ustr) &&
(base_bidi != EVAS_BIDI_PARAGRAPH_RTL))
{
len = -1;
goto cleanup;
@ -255,6 +257,7 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len,
#endif
bidi_props = evas_bidi_paragraph_props_new();
bidi_props->direction = base_bidi;
/* Prep work for reordering */
char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len);
@ -281,7 +284,7 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len,
for (itr = segment_idxs ; *itr > 0 ; itr++)
{
direction = EVAS_BIDI_PARAGRAPH_NEUTRAL;
direction = base_bidi;
if (!fribidi_get_par_embedding_levels(char_types + pos,
*itr - pos,
&direction,
@ -308,7 +311,7 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len,
pos = *itr + 1;
}
direction = EVAS_BIDI_PARAGRAPH_NEUTRAL;
direction = base_bidi;
if (!fribidi_get_par_embedding_levels(char_types + pos,
len - pos,
&direction,

View File

@ -143,7 +143,7 @@ Eina_Bool
evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, size_t start, size_t len, const Evas_BiDi_Paragraph_Props *props, EvasBiDiStrIndex **_v_to_l);
Evas_BiDi_Paragraph_Props *
evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len, int *segment_idxs) EINA_ARG_NONNULL(1) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len, int *segment_idxs, EvasBiDiParType base_bidi) EINA_ARG_NONNULL(1) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
void
evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst);

View File

@ -29,6 +29,7 @@ static const Evas_Test_Case etc[] = {
{ "Meshes", evas_test_mesh },
{ "Masking", evas_test_mask },
{ "Evas GL", evas_test_evasgl },
{ "Object Smart", evas_test_object_smart },
{ NULL, NULL }
};

View File

@ -14,5 +14,6 @@ void evas_test_image_object(TCase *tc);
void evas_test_mesh(TCase *tc);
void evas_test_mask(TCase *tc);
void evas_test_evasgl(TCase *tc);
void evas_test_object_smart(TCase *tc);
#endif /* _EVAS_SUITE_H */

View File

@ -0,0 +1,180 @@
/*
* TODO:
* * Test different font lodaing mechanisms.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <Eina.h>
#include "evas_suite.h"
#include "Evas.h"
#include "evas_tests_helpers.h"
#define TEST_FONT_SOURCE TESTS_SRC_DIR "/TestFont.eet"
#define TEST_TEXTBLOCK_FONT "font=DejaVuSans font_source=" TEST_FONT_SOURCE
#define TEST_TEXTBLOCK_FONT_SIZE "14"
#define TEST_TEXT_FONT "DejaVuSans,UnDotum"
#define TEST_TEXT_FONT_SIZE 14
static const char *style_buf =
"DEFAULT='" TEST_TEXTBLOCK_FONT " font_size="TEST_TEXTBLOCK_FONT_SIZE" color=#000 text_class=entry'"
"newline='br'"
"b='+ font_weight=bold'";
#define START_EVAS_OBJECT_SMART_TEST() \
Evas *evas; \
Evas_Object *smart_obj; \
evas = EVAS_TEST_INIT_EVAS(); \
smart_obj = evas_object_box_add(evas); \
fail_if(!smart_obj); \
do \
{ \
} \
while (0)
#define END_EVAS_OBJECT_SMART_TEST() \
do \
{ \
evas_object_del(smart_obj); \
evas_free(evas); \
evas_shutdown(); \
} \
while (0)
#define ADD_EVAS_TEXTBLOCK() \
Evas_Object *tb; \
Evas_Textblock_Style *st; \
Evas_Textblock_Cursor *cur; \
evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
tb = evas_object_textblock_add(evas); \
fail_if(!tb); \
evas_object_textblock_legacy_newline_set(tb, EINA_FALSE); \
st = evas_textblock_style_new(); \
fail_if(!st); \
evas_textblock_style_set(st, style_buf); \
fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \
evas_object_textblock_style_set(tb, st); \
cur = evas_object_textblock_cursor_new(tb); \
do \
{ \
} \
while (0)
#define ADD_EVAS_TEXT() \
Evas_Object *to; \
evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
to = evas_object_text_add(evas); \
fail_if(!to); \
evas_object_text_font_source_set(to, TEST_FONT_SOURCE); \
evas_object_text_font_set(to, TEST_TEXT_FONT, TEST_TEXT_FONT_SIZE); \
do \
{ \
} \
while (0)
#define DELETE_EVAS_TEXTBLOCK() \
do \
{ \
evas_textblock_cursor_free(cur); \
evas_object_del(tb); \
evas_textblock_style_free(st); \
} \
while (0)
#define DELETE_EVAS_TEXT() \
do \
{ \
evas_object_del(to); \
} \
while (0)
START_TEST(evas_object_smart_paragraph_direction)
{
START_EVAS_OBJECT_SMART_TEST();
ADD_EVAS_TEXTBLOCK();
evas_object_resize(tb, 500, 500);
evas_object_textblock_text_markup_set(tb, "%^&amp;");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "%^&amp;"));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_INHERIT);
ADD_EVAS_TEXT();
evas_object_text_text_set(to, "%^&amp;");
fail_if(strcmp(evas_object_text_text_get(to), "%^&amp;"));
evas_object_paragraph_direction_set(to, EVAS_BIDI_DIRECTION_INHERIT);
/* Test evas_object_paragraph_direction_set API with smart objects. */
Evas_Object *smart_child = evas_object_box_add(evas);
Evas_BiDi_Direction dir;
Evas_Coord x, y, w, h;
Evas_Coord xx, yy, ww, hh;
evas_object_smart_member_add(smart_child, smart_obj);
evas_object_smart_member_add(tb, smart_child);
evas_object_smart_member_add(to, smart_child);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if(evas_object_text_direction_get(to) == EVAS_BIDI_DIRECTION_RTL);
/* Change paragraph direction of smart parent object */
evas_object_paragraph_direction_set(smart_obj, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_RTL);
/* The paragraph direction of smart member object has to be reset
if smart member object is removed from smart parent. */
evas_object_smart_member_del(smart_child);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
fail_if(evas_object_text_direction_get(to) == EVAS_BIDI_DIRECTION_RTL);
/* The paragraph direction of smart member object has to be changed
if smart member object is appended to smart parent. */
evas_object_smart_member_add(smart_child, smart_obj);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_RTL);
/* Ignore smart parent's paragraph direction */
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
evas_object_paragraph_direction_set(to, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
fail_if(evas_object_text_direction_get(to) == EVAS_BIDI_DIRECTION_RTL);
evas_object_smart_member_del(tb);
evas_object_smart_member_del(to);
evas_object_del(smart_child);
DELETE_EVAS_TEXTBLOCK();
DELETE_EVAS_TEXT();
END_EVAS_OBJECT_SMART_TEST();
}
END_TEST
void evas_test_object_smart(TCase *tc)
{
tcase_add_test(tc, evas_object_smart_paragraph_direction);
}

View File

@ -362,6 +362,15 @@ START_TEST(evas_text_set_get)
fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_LTR);
#endif
#ifdef HAVE_FRIBIDI
/* Check direction with evas_object_paragraph_direction_set API */
evas_object_text_text_set(to, "12345");
fail_if(evas_object_text_direction_get(to) == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(to, EVAS_BIDI_DIRECTION_RTL);
fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(to, EVAS_BIDI_DIRECTION_NEUTRAL);
#endif
END_TEXT_TEST();
}
END_TEST

View File

@ -421,6 +421,7 @@ START_TEST(evas_textblock_cursor)
fail_if(evas_textblock_cursor_compare(main_cur, cur));
}
#ifdef HAVE_FRIBIDI
/* Check direction */
evas_object_textblock_text_markup_set(tb, "test");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "test"));
@ -442,8 +443,199 @@ START_TEST(evas_textblock_cursor)
evas_textblock_cursor_geometry_get(cur, NULL, NULL, NULL, NULL, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
evas_object_textblock_text_markup_set(tb, "123");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "123"));
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, NULL, NULL, NULL, NULL, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, NULL, NULL, NULL, NULL, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_LTR);
evas_object_textblock_text_markup_set(tb, "%^&amp;");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "%^&amp;"));
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, NULL, NULL, NULL, NULL, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, NULL, NULL, NULL, NULL, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_LTR);
/* Check direction with evas_object_paragraph_direction_set API */
{
Evas_Coord xx, yy, ww, hh;
/* LTR text case */
evas_object_textblock_text_markup_set(tb, "test");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "test"));
/* EVAS_TEXTBLOCK_CURSOR_UNDER */
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
/* EVAS_TEXTBLOCK_CURSOR_BEFORE */
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
/* RTL text case */
evas_object_textblock_text_markup_set(tb, "עוד פסקה");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "עוד פסקה"));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x <= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x <= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
/* NEUTRAL(European Number) text case */
/* It doesn't change characters sequence. */
evas_object_textblock_text_markup_set(tb, "123");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "123"));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
/* NEUTRAL(Other Neutrals) text case */
/* It changes characters sequence. */
evas_object_textblock_text_markup_set(tb, "%^&amp;");
fail_if(strcmp(evas_object_textblock_text_markup_get(tb), "%^&amp;"));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_UNDER);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &x, &y, &w, &h, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_RTL);
dir = EVAS_BIDI_DIRECTION_LTR;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir != EVAS_BIDI_DIRECTION_RTL);
fail_if((x >= xx) || (y != yy) || (w != ww) || (h != hh));
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_LTR);
dir = EVAS_BIDI_DIRECTION_RTL;
evas_textblock_cursor_geometry_get(cur, &xx, &yy, &ww, &hh, &dir,
EVAS_TEXTBLOCK_CURSOR_BEFORE);
fail_if(dir == EVAS_BIDI_DIRECTION_RTL);
fail_if((x != xx) || (y != yy) || (w != ww) || (h != hh));
/* Reset paragraph direction */
evas_object_paragraph_direction_set(tb, EVAS_BIDI_DIRECTION_NEUTRAL);
}
#ifdef HAVE_FRIBIDI
evas_object_textblock_text_markup_set(tb,
"testנסיוןtestנסיון<ps/>"
"נסיוןtestנסיוןtest<ps/>"