unsigned char style;
Evas_BiDi_Props intl_props;
- Evas_BiDi_Paragraph_Props paragraph_bidi_props;
} cur, prev;
float ascent, descent;
/* DO II */
/*Update intl_props*/
#ifdef BIDI_SUPPORT
- evas_bidi_update_props(text, o->cur.intl_props.props);
+ evas_bidi_paragraph_props_unref(o->cur.intl_props.props);
+ o->cur.intl_props.props = evas_bidi_paragraph_props_get(text);
#endif
if (o->cur.text) eina_ustringshare_del(o->cur.text);
if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
o = calloc(1, sizeof(Evas_Object_Text));
o->magic = MAGIC_OBJ_TEXT;
o->prev = o->cur;
- o->cur.intl_props.props = &o->cur.paragraph_bidi_props;
-#ifdef BIDI_SUPPORT
- o->cur.intl_props.props->direction = EVAS_BIDI_PARAGRAPH_NATURAL;
-#endif
+ o->cur.intl_props.props = evas_bidi_paragraph_props_new();
return o;
}
if (o->cur.font) eina_stringshare_del(o->cur.font);
if (o->cur.source) eina_stringshare_del(o->cur.source);
if (o->engine_data) evas_font_free(obj->layer->evas, o->engine_data);
- if (o->cur.intl_props.props->embedding_levels) free(o->cur.intl_props.props->embedding_levels);
- if (o->cur.intl_props.props->char_types) free(o->cur.intl_props.props->char_types);
+ evas_bidi_props_clean(&o->cur.intl_props);
o->magic = 0;
free(o);
}
{
EINA_INLIST;
Eina_UStrbuf *unicode;
- char * utf8;
+ char *utf8;
Evas_Object_Textblock_Node_Format *format_node;
- Evas_BiDi_Paragraph_Props bidi_props;
+ Evas_BiDi_Paragraph_Props *bidi_props;
};
struct _Evas_Object_Textblock_Node_Format
if (c->align_auto && c->ln && c->ln->items)
{
if (c->ln->items->source_node &&
+
EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(
- c->ln->items->source_node->bidi_props.direction))
+ c->ln->items->source_node->bidi_props))
{
/* Align right*/
return 1.0;
new_it->source_node = pit->source_node;
new_it->source_pos = pit->source_pos + index;
new_it->bidi_props.start = new_it->source_pos;
- new_it->bidi_props.props = &new_it->source_node->bidi_props;
+ new_it->bidi_props.props = new_it->source_node->bidi_props;
# ifdef BIDI_SUPPORT
evas_bidi_shape_string(new_it->text, &new_it->bidi_props,
eina_unicode_strlen(new_it->text));
if (it->source_node)
{
it->bidi_props.start = it->source_pos;
- it->bidi_props.props = &it->source_node->bidi_props;
+ it->bidi_props.props = it->source_node->bidi_props;
# ifdef BIDI_SUPPORT
evas_bidi_shape_string(it->text, &it->bidi_props,
eina_unicode_strlen(it->text));
eina_ustrbuf_free(n->unicode);
if (n->utf8)
free(n->utf8);
+ if (&n->bidi_props)
+ evas_bidi_paragraph_props_unref(n->bidi_props);
free(n);
}
n = calloc(1, sizeof(Evas_Object_Textblock_Node_Text));
n->unicode = eina_ustrbuf_new();
+ n->bidi_props = evas_bidi_paragraph_props_new();
#ifdef BIDI_SUPPORT
- n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
+ n->bidi_props->direction = EVAS_BIDI_PARAGRAPH_NATURAL;
#endif
return n;
eina_ustrbuf_append_length(n->unicode, text + start, len);
eina_ustrbuf_remove(cur->node->unicode, start, start + len);
#ifdef BIDI_SUPPORT
- /* Reset paragraph direction */
- n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
- evas_bidi_update_props(eina_ustrbuf_string_get(n->unicode),
- &n->bidi_props);
- cur->node->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
- evas_bidi_update_props(eina_ustrbuf_string_get(cur->node->unicode),
- &cur->node->bidi_props);
+ evas_bidi_paragraph_props_unref(n->bidi_props);
+ n->bidi_props = evas_bidi_paragraph_props_get(
+ eina_ustrbuf_string_get(n->unicode));
+
+ evas_bidi_paragraph_props_unref(cur->node->bidi_props);
+ cur->node->bidi_props = evas_bidi_paragraph_props_get(
+ eina_ustrbuf_string_get(cur->node->unicode));
#endif
}
else
if (fnode && (fnode->text_node == cur->node))
fnode->offset += len;
#ifdef BIDI_SUPPORT
- /* Reset paragraph direction */
- n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
- evas_bidi_update_props(eina_ustrbuf_string_get(n->unicode), &n->bidi_props);
+ evas_bidi_paragraph_props_unref(n->bidi_props);
+ n->bidi_props = evas_bidi_paragraph_props_get(eina_ustrbuf_string_get(n->unicode));
#endif
_evas_textblock_changed(o, cur->obj);
free(text);
_evas_textblock_cursor_nodes_merge(cur);
}
#ifdef BIDI_SUPPORT
- /* Reset paragraph direction */
- n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
- evas_bidi_update_props(eina_ustrbuf_string_get(n->unicode),
- &n->bidi_props);
+ evas_bidi_paragraph_props_unref(n->bidi_props);
+ n->bidi_props = evas_bidi_paragraph_props_get(eina_ustrbuf_string_get(n->unicode));
#endif
if (cur->pos == eina_ustrbuf_length_get(n->unicode))
}
#ifdef BIDI_SUPPORT
- /* Reset paragraph direction */
- n1->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
- evas_bidi_update_props(eina_ustrbuf_string_get(n1->unicode),
- &n1->bidi_props);
+ evas_bidi_paragraph_props_unref(n1->bidi_props);
+ n1->bidi_props = evas_bidi_paragraph_props_get(
+ eina_ustrbuf_string_get(n1->unicode));
#endif
evas_textblock_cursor_copy(cur1, cur2);
{
FriBidiChar *ustr, *base_ustr = NULL;
- if (!EVAS_BIDI_IS_BIDI_PROP(bidi_props->props))
+ if (!bidi_props->props)
return EINA_FALSE;
/* The size of fribidichar is different than eina_unicode, convert */
/*FIXME: Make this comparison at compile time and compile out
- * unwanted code. - In all of this source file. */
+ * unwanted code. - In all of this source file. (including the actual
+ * function declerations. */
if (sizeof(Eina_Unicode) != sizeof(FriBidiChar))
{
base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar));
/**
* @internal
- * Updates the bidi properties according to ustr. First checks to see if the
- * passed has rtl chars, if not, it cleans intl_props and returns.
- * Otherwise, it essentially frees the old fields, allocates new fields, and
- * populates them.
- * On error: bidi_props is cleaned.
+ * Allocates bidi properties according to ustr. First checks to see if the
+ * passed has rtl chars, if not, it returns NULL.
*
* @param ustr The string to update according to.
- * @param bidi_props the bidi_props to update.
- * @return returns the length of the string on success, a negative value on error.
+ * @return returns allocated paragraph props on success, NULL otherwise.
*/
-int
-evas_bidi_update_props(const Eina_Unicode *eina_ustr, Evas_BiDi_Paragraph_Props *bidi_props)
+
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr)
{
+ Evas_BiDi_Paragraph_Props *bidi_props = NULL;
EvasBiDiCharType *char_types = NULL;
EvasBiDiLevel *embedding_levels = NULL;
const FriBidiChar *ustr;
size_t len;
if (!eina_ustr)
- return -2;
+ return NULL;
+
len = eina_unicode_strlen(eina_ustr);
goto cleanup;
}
+ bidi_props = evas_bidi_paragraph_props_new();
+
/* Prep work for reordering */
char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len);
if (!char_types)
free(bidi_props->char_types);
}
bidi_props->char_types = char_types;
-
- bidi_props->len = len;
if (base_ustr) free(base_ustr);
- return len;
+ return bidi_props;
/* Cleanup */
cleanup:
if (char_types) free(char_types);
if (embedding_levels) free(embedding_levels);
if (base_ustr) free(base_ustr);
- evas_bidi_paragraph_props_clean(bidi_props); /*Mark that we don't need bidi handling */
- return len;
+ if (bidi_props) evas_bidi_paragraph_props_unref(bidi_props); /* Clean up the bidi props */
+ return NULL;
}
-int
-evas_bidi_update_props_dup(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst)
+/**
+ * @internal
+ * Copies dst to src and refs (doesn't copy) the paragraph props.
+ *
+ * @param src the props to copy
+ * @param dst the props to copy to.
+ */
+void
+evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst)
{
dst->start = src->start;
- dst->props = NULL;
- if (!src->props) return 1;
- dst->props = malloc(sizeof(Evas_BiDi_Paragraph_Props));
- if (!dst->props) return 0;
- if (src->props->len > 0)
- {
- if (src->props->char_types)
- {
- dst->props->char_types =
- malloc(sizeof(EvasBiDiCharType) * src->props->len);
- if (!dst->props->char_types)
- {
- free(dst->props);
- dst->props = NULL;
- dst->start = 0;
- return 0;
- }
- memcpy(dst->props->char_types, src->props->char_types,
- sizeof(EvasBiDiCharType) * src->props->len);
- }
- else
- dst->props->char_types = NULL;
- if (src->props->embedding_levels)
- {
- dst->props->embedding_levels =
- malloc(sizeof(EvasBiDiLevel) * src->props->len);
- if (!dst->props->embedding_levels)
- {
- if (dst->props->char_types) free(dst->props->char_types);
- free(dst->props);
- dst->props = NULL;
- dst->start = 0;
- return 0;
- }
- memcpy(dst->props->embedding_levels, src->props->embedding_levels,
- sizeof(EvasBiDiLevel) * src->props->len);
- }
- else
- dst->props->embedding_levels = NULL;
- }
- else
- {
- dst->props->char_types = NULL;
- dst->props->embedding_levels = NULL;
- dst->props->len = 0;
- }
- dst->props->len = src->props->len;
- dst->props->direction = src->props->direction;
- return 1;
+ dst->props = evas_bidi_paragraph_props_ref(src->props);
}
/**
FriBidiChar *ustr, *base_ustr = NULL;
size_t len;
- if (!EVAS_BIDI_IS_BIDI_PROP(intl_props->props))
+ if (!intl_props->props)
return EINA_FALSE;
len = eina_unicode_strlen(eina_ustr);
if (_v_to_l) {
- int i;
+ size_t i;
v_to_l = *_v_to_l = calloc(len, sizeof(EvasBiDiStrIndex));
if (!v_to_l)
{
* Checks if the char is rtl oriented. I.e even a neutral char can become rtl
* if surrounded by rtl chars.
*
- * @param embedded_level_list the bidi embedding list.
+ * @param bidi_props The bidi properties
* @param index the index of the string.
* @return #EINA_TRUE if true, #EINA_FALSE otherwise.
*/
Eina_Bool
-evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index)
+evas_bidi_is_rtl_char(const Evas_BiDi_Props *bidi_props, EvasBiDiStrIndex index)
{
- if(!embedded_level_list || index < 0)
+ if(!bidi_props || !bidi_props->props || index < 0)
return EINA_FALSE;
- return (FRIBIDI_IS_RTL(embedded_level_list[index])) ? EINA_TRUE : EINA_FALSE;
+ return (FRIBIDI_IS_RTL(
+ bidi_props->props->embedding_levels[index + bidi_props->start]))
+ ? EINA_TRUE : EINA_FALSE;
+}
+
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_new(void)
+{
+ Evas_BiDi_Paragraph_Props *ret;
+ ret = calloc(1, sizeof(Evas_BiDi_Paragraph_Props));
+ ret->direction = EVAS_BIDI_PARAGRAPH_NATURAL;
+ ret->refcount = 1;
+
+ return ret;
}
/**
* @internal
+ * Refs the bidi props.
+ *
+ * @param bidi_props the props to ref.
+ */
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_ref(Evas_BiDi_Paragraph_Props *bidi_props)
+{
+ if (!bidi_props) return NULL;
+ BIDILOCK();
+
+ bidi_props->refcount++;
+ BIDIUNLOCK();
+ return bidi_props;
+}
+
+/**
+ * @internal
+ * Unrefs and potentially frees the props.
+ *
+ * @param bidi_props the properties to unref
+ */
+void
+evas_bidi_paragraph_props_unref(Evas_BiDi_Paragraph_Props *bidi_props)
+{
+ if (!bidi_props) return;
+ BIDILOCK();
+
+ if (--bidi_props->refcount == 0)
+ {
+ evas_bidi_paragraph_props_clean(bidi_props);
+ free(bidi_props);
+ }
+ BIDIUNLOCK();
+}
+
+
+/**
+ * @internal
* Cleans the paragraph properties.
*
* @param bidi_props the properties to clean.
evas_bidi_props_clean(Evas_BiDi_Props *bidi_props)
{
if (!bidi_props) return;
- evas_bidi_paragraph_props_clean(bidi_props->props);
+ evas_bidi_paragraph_props_unref(bidi_props->props);
bidi_props->props = NULL;
}
/**
struct _Evas_BiDi_Paragraph_Props {
EvasBiDiCharType *char_types; /* BiDi char types */
EvasBiDiLevel *embedding_levels; /* BiDi embedding levels */
- int len; /* length of char_types & embedding_levels */
+ int refcount; /* The number of references to this object */
#ifdef USE_FRIBIDI
EvasBiDiParType direction;
#endif
#define EVAS_BIDI_PARAGRAPH_WLTR FRIBIDI_PAR_WLTR
#define EVAS_BIDI_PARAGRAPH_WRTL FRIBIDI_PAR_WRTL
-#define EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(direction) \
- (((direction == EVAS_BIDI_PARAGRAPH_RTL) || \
- (direction == EVAS_BIDI_PARAGRAPH_WRTL)) ? \
- EINA_TRUE : EINA_FALSE)
+#define EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(x) \
+ (((x) && \
+ ((x->direction == EVAS_BIDI_PARAGRAPH_RTL) || \
+ (x->direction == EVAS_BIDI_PARAGRAPH_WRTL))) ? \
+ EINA_TRUE : EINA_FALSE)
-# define EVAS_BIDI_IS_BIDI_PROP(intl_props) ((intl_props) && (intl_props)->char_types)
# define evas_bidi_position_visual_to_logical(list, position) \
(list) ? list[position] : position;
evas_bidi_is_rtl_str(const Eina_Unicode *str);
Eina_Bool
-evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index);
+evas_bidi_is_rtl_char(const Evas_BiDi_Props *bidi_props, EvasBiDiStrIndex index);
Eina_Bool
evas_bidi_props_reorder_line(Eina_Unicode *text, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l);
-int
-evas_bidi_update_props(const Eina_Unicode *text, Evas_BiDi_Paragraph_Props *intl_props) EINA_ARG_NONNULL(1, 2);
-int
-evas_bidi_update_props_dup(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst);
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr) 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);
Eina_Bool
evas_bidi_shape_string(Eina_Unicode *ustr, const Evas_BiDi_Props *intl_props, size_t len);
void
evas_bidi_paragraph_props_clean(Evas_BiDi_Paragraph_Props *bidi_props) EINA_ARG_NONNULL(1);
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_ref(Evas_BiDi_Paragraph_Props *bidi_props) EINA_ARG_NONNULL(1);
+
+void
+evas_bidi_paragraph_props_unref(Evas_BiDi_Paragraph_Props *bidi_props) EINA_ARG_NONNULL(1);
+
+Evas_BiDi_Paragraph_Props *
+evas_bidi_paragraph_props_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
+
#endif
/**
* @}
#endif
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
Eina_Unicode *visual_text;
visual_text = eina_unicode_strdup(in_text);
{
text = in_text;
}
- LKU(lock_fribidi);
#endif
{
int kern = 0;
# ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props && intl_props->props &&
- evas_bidi_is_rtl_char(intl_props->props->embedding_levels, char_index) &&
+ evas_bidi_is_rtl_char(intl_props, char_index) &&
ci->fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern))
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
pen_x += kern;
}
- LKU(lock_fribidi);
-# else
-
+# else
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
pen_x += kern;
# endif
static int initialised = 0;
LK(lock_font_draw); // for freetype2 API calls
-LK(lock_fribidi); // for fribidi API calls
+LK(lock_bidi); // for evas bidi internal usage.
EAPI void
evas_common_font_init(void)
evas_common_font_load_init();
evas_common_font_draw_init();
LKI(lock_font_draw);
- LKI(lock_fribidi);
+ LKI(lock_bidi);
}
EAPI void
if (initialised != 0) return;
LKD(lock_font_draw);
- LKD(lock_fribidi);
-
+ LKD(lock_bidi);
+
evas_common_font_load_shutdown();
evas_common_font_cache_set(0);
evas_common_font_flush();
#ifdef BUILD_PTHREAD
extern LK(lock_font_draw); // for freetype2 API calls
-extern LK(lock_fribidi); // for fribidi API calls
+extern LK(lock_bidi); // for fribidi API calls
#endif
# if defined(EVAS_FRAME_QUEUING) || defined(BUILD_PIPE_RENDER)
# define FTLOCK() LKL(lock_font_draw)
# define FTUNLOCK() LKU(lock_font_draw)
-# define FBDLOCK() LKL(lock_fribidi)
-# define FBDUNLOCK() LKU(lock_fribidi)
+# define BIDILOCK() LKL(lock_bidi)
+# define BIDIUNLOCK() LKU(lock_bidi)
# else
# define FTLOCK(x)
# define FTUNLOCK(x)
-# define FBDLOCK()
-# define FBDUNLOCK()
+# define BIDILOCK()
+# define BIDIUNLOCK()
# endif
#endif /* !_EVAS_FONT_PRIVATE_H */
(pface == fi->src->ft.face))
{
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
- evas_bidi_is_rtl_char(intl_props->props->embedding_levels, char_index) &&
+ evas_bidi_is_rtl_char(intl_props, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
}
- LKU(lock_fribidi);
#else
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
(pface == fi->src->ft.face))
{
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
- evas_bidi_is_rtl_char(intl_props->props->embedding_levels, char_index) &&
+ evas_bidi_is_rtl_char(intl_props, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
}
- LKU(lock_fribidi);
#else
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
EvasBiDiStrIndex *visual_to_logical = NULL;
Eina_Unicode *visual_text;
- LKL(lock_fribidi);
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
{
text = in_text;
}
len = eina_unicode_strlen(text);
- LKU(lock_fribidi);
#endif
fi = fn->fonts->data;
desc = evas_common_font_max_descent_get(fn);
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* Get the position in the visual string because those are the coords we care about */
position = evas_bidi_position_logical_to_visual(visual_to_logical, len, pos);
- LKU(lock_fribidi);
#else
position = pos;
#endif
EvasBiDiStrIndex *visual_to_logical = NULL;
Eina_Unicode *visual_text;
- LKL(lock_fribidi);
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
text = in_text;
}
len = eina_unicode_strlen(text);
- LKU(lock_fribidi);
#endif
fi = fn->fonts->data;
if (cw) *cw = chr_w;
if (ch) *ch = asc + desc;
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* we found the char position of the wanted char in the
* visual string, we now need to translate it to the
* position in the logical string */
position = evas_bidi_position_visual_to_logical(visual_to_logical, position);
- LKU(lock_fribidi);
#endif
ret_val = position;
goto end;
(pface == fi->src->ft.face))
{
#ifdef BIDI_SUPPORT
- LKL(lock_fribidi);
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
- evas_bidi_is_rtl_char(intl_props->props->embedding_levels,
- char_index) && fg->glyph->advance.x >> 16 > 0)
+ evas_bidi_is_rtl_char(intl_props, char_index) &&
+ fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index,
&kern))
&kern))
pen_x += kern;
}
- LKU(lock_fribidi);
-#else
+#else
if (evas_common_font_query_kerning(fi, prev_index, index,
&kern))
pen_x += kern;
op->op.text.y = y;
op->op.text.text = eina_unicode_strdup(text);
#ifdef BIDI_SUPPORT
- evas_bidi_update_props_dup(intl_props, &(op->op.text.intl_props));
+ evas_bidi_props_copy_and_ref(intl_props, &(op->op.text.intl_props));
#endif
#ifdef EVAS_FRAME_QUEUING
LKL(fn->ref_fq_add);