typedef struct _Evas_Object_Textgrid_Rect Evas_Object_Textgrid_Rect;
typedef struct _Evas_Object_Textgrid_Text Evas_Object_Textgrid_Text;
typedef struct _Evas_Object_Textgrid_Line Evas_Object_Textgrid_Line;
-typedef struct _Evas_Textgrid_Hash_Master Evas_Textgrid_Hash_Master;
-typedef struct _Evas_Textgrid_Hash_Glyphs Evas_Textgrid_Hash_Glyphs;
-
-struct _Evas_Textgrid_Hash_Master
-{
- int next[16];
-};
-
-struct _Evas_Textgrid_Hash_Glyphs
-{
- Evas_Text_Props props[256];
-};
struct _Evas_Textgrid_Data
{
Evas_Font_Set *font;
- Evas_Textgrid_Hash_Master *master;
- Evas_Textgrid_Hash_Glyphs *glyphs;
- unsigned char *master_used;
- unsigned char *glyphs_used;
- unsigned int master_length;
- unsigned int glyphs_length;
-
- unsigned int last_mask;
- Evas_Textgrid_Hash_Glyphs *last_glyphs;
-
- Eina_Array glyphs_cleanup;
-
unsigned int changed : 1;
unsigned int core_change : 1;
unsigned int row_change : 1;
{
unsigned char r, g, b, a;
int x;
- unsigned int text_props_index;
+ Evas_Text_Props text_props;
};
struct _Evas_Object_Textgrid_Line
NULL
};
-/* almost generic private array data type */
-static int
-evas_object_textgrid_textprop_get(Evas_Object *eo_obj, Evas_Textgrid_Data *o, Eina_Unicode codepoint,
- unsigned int glyphs_index, unsigned char *used)
-{
- Evas_Textgrid_Hash_Glyphs *glyph;
- unsigned char idx = codepoint & 0xFF;
-
- glyph = &(o->glyphs[glyphs_index]);
-
- if (!glyph->props[idx].info)
- {
- Evas_Font_Instance *script_fi = NULL;
- Evas_Font_Instance *cur_fi = NULL;
- Evas_Script_Type script;
-
- script = evas_common_language_script_type_get(&codepoint, 1);
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
- ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi, script, &codepoint, 1);
- memset(&(glyph->props[idx]), 0, sizeof(Evas_Text_Props));
- evas_common_text_props_script_set(&(glyph->props[idx]), script);
- ENFN->font_text_props_info_create(ENDT, script_fi, &codepoint,
- &(glyph->props[idx]), NULL, 0, 1,
- EVAS_TEXT_PROPS_MODE_NONE,
- o->cur.font_description->lang);
- (*used)++;
- }
- else
- {
- evas_common_text_props_content_ref(&(glyph->props[idx]));
- }
-
- return glyphs_index << 8 | (unsigned int) idx;
-}
-
-static int
-evas_object_textgrid_textprop_ref(Evas_Object *eo_obj, Evas_Textgrid_Data *o, Eina_Unicode codepoint)
-{
- unsigned int mask = 0xF0000000;
- unsigned int shift = 28;
- unsigned int offset = 0;
- unsigned int glyphs_index;
-
- if (o->last_glyphs)
- {
- if ((o->last_mask) && ((o->last_mask & codepoint) == o->last_mask))
- goto end;
- }
-
- if (!o->master)
- {
- o->master = calloc(6, sizeof (Evas_Textgrid_Hash_Master));
- o->master_used = calloc(6, sizeof (unsigned char));
- o->glyphs = calloc(1, sizeof (Evas_Textgrid_Hash_Glyphs));
- o->glyphs_used = calloc(1, sizeof (unsigned char));
- if (!o->master || !o->master_used || !o->glyphs || !o->glyphs_used)
- {
- free(o->master);
- o->master = NULL;
- free(o->master_used);
- o->master_used = NULL;
- free(o->glyphs);
- o->glyphs = NULL;
- free(o->glyphs_used);
- o->glyphs_used = NULL;
- return 0xFFFFFFFF;
- }
-
- while (shift > 8)
- {
- o->master[offset].next[(mask & codepoint) >> shift] = offset + 1;
- o->master_used[offset] = 1;
- offset++;
- shift -= 4;
- mask >>= 4;
- }
-
- o->glyphs_length = 1;
- o->master_length = 6;
- o->master[5].next[(codepoint & 0xF00) >> 8] = 0xFF000000;
- o->last_glyphs = o->glyphs;
- o->last_mask = codepoint & 0xFFFFFF00;
-
- goto end;
- }
-
- while ((shift > 8)
- && (o->master[offset].next[(codepoint & mask) >> shift] != 0))
- {
- offset = o->master[offset].next[(codepoint & mask) >> shift];
- mask >>= 4;
- shift -= 4;
- }
-
- if (shift > 8)
- {
- Evas_Textgrid_Hash_Master *tmp;
- unsigned char *tmp_used;
- int master_count;
- int count;
- int end;
-
- count = (shift - 8) / 4;
- master_count = o->master_length + count;
-
- /* FIXME: find empty entry */
- tmp = realloc(o->master, master_count * sizeof (Evas_Textgrid_Hash_Master));
- if (!tmp) return 0xFFFFFFFF;
- o->master = tmp;
- tmp_used = realloc(o->master_used, master_count);
- if (!tmp_used) return 0xFFFFFFFF;
- o->master_used = tmp_used;
-
- memset(o->master + o->master_length, 0, count * sizeof (Evas_Textgrid_Hash_Master));
- memset(o->master_used + o->master_length, 1, count);
- end = o->master_length;
- o->master_length = master_count;
-
- while (shift > 8)
- {
- o->master[offset].next[(mask & codepoint) >> shift] = end;
- o->master_used[offset] = 1;
- end++;
- offset = end;
- shift -= 4;
- mask >>= 4;
- }
- offset--;
- }
- if ((o->master[offset].next[(codepoint & mask) >> shift] == 0)
- || ((o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF) >= o->glyphs_length))
- {
- Evas_Textgrid_Hash_Glyphs *tmp;
- unsigned char *tmp_used;
- int count;
-
- /* FIXME: find empty entry */
- if (o->master[offset].next[(codepoint & mask) >> shift] == 0)
- count = o->glyphs_length + 1;
- else
- count = (o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF) + 1;
- tmp = realloc(o->glyphs, count * sizeof (Evas_Textgrid_Hash_Glyphs));
- if (!tmp) return 0xFFFFFFFF;
- o->glyphs = tmp;
- tmp_used = realloc(o->glyphs_used, count * sizeof (unsigned char));
- if (!tmp_used) return 0xFFFFFFFF;
- o->glyphs_used = tmp_used;
-
- // FIXME: What should we write when allocating more than one new entry?
- o->master[offset].next[(codepoint & mask) >> shift] = o->glyphs_length + 0xFF000000;
-
- memset(o->glyphs + o->glyphs_length, 0, (count - o->glyphs_length) * sizeof (Evas_Textgrid_Hash_Glyphs));
- memset(o->glyphs_used, 0, (count - o->glyphs_length) * sizeof(o->glyphs_used[0]));
- o->glyphs_length = count;
- }
-
- o->last_glyphs = o->glyphs + (o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF);
- o->last_mask = codepoint & 0xFFFFFF00;
-
- end:
- glyphs_index = o->last_glyphs - o->glyphs;
- return evas_object_textgrid_textprop_get(eo_obj, o, codepoint, glyphs_index,
- &(o->glyphs_used[glyphs_index]));
-}
-
-static Evas_Text_Props *
-_textprop_from_idx(Evas_Textgrid_Data *o, unsigned int props_index)
-{
- return &(o->glyphs[props_index >> 8].props[props_index & 0xFF]);
-}
-
-
-static void
-evas_object_textgrid_textprop_unref(Evas_Textgrid_Data *o, unsigned int props_index)
-{
- Evas_Text_Props *props;
-
- props = _textprop_from_idx(o, props_index);
-
- if (props->info)
- {
- if (props->info->refcount == 1)
- eina_array_push(&o->glyphs_cleanup,
- (void *)((uintptr_t)props_index));
- else
- {
- evas_common_text_props_content_nofree_unref(props);
- }
- }
-}
-
/* all nice and private */
static void
evas_object_textgrid_init(Evas_Object *eo_obj)
o->prev = o->cur;
eina_array_step_set(&o->cur.palette_standard, sizeof (Eina_Array), 16);
eina_array_step_set(&o->cur.palette_extended, sizeof (Eina_Array), 16);
- eina_array_step_set(&o->glyphs_cleanup, sizeof (Eina_Array), 16);
}
static void
-evas_object_textgrid_row_clear(Evas_Textgrid_Data *o, Evas_Object_Textgrid_Row *r)
+evas_object_textgrid_row_clear(Evas_Textgrid_Data *o EINA_UNUSED,
+ Evas_Object_Textgrid_Row *r)
{
int i;
if (r->texts)
{
for (i = 0; i < r->texts_num; i++)
- if (r->texts[i].text_props_index != 0xFFFFFFFF)
- {
- evas_object_textgrid_textprop_unref(o, r->texts[i].text_props_index);
- r->texts[i].text_props_index = 0xFFFFFFFF;
- }
+ evas_common_text_props_content_unref(&(r->texts[i].text_props));
free(r->texts);
r->texts = NULL;
r->texts_num = 0;
free(c);
eina_array_flush(&o->cur.palette_extended);
- while (eina_array_count(&o->glyphs_cleanup) > 0)
- {
- Evas_Text_Props *prop;
- unsigned int props_index;
-
- props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
- prop = &(o->glyphs[props_index >> 8].props[props_index & 0xFF]);
-
- evas_common_text_props_content_nofree_unref(prop);
- if (!prop->info)
- {
- o->glyphs_used[props_index >> 8]--;
-
- if (!o->glyphs_used[props_index >> 8])
- {
- /* FIXME: cleanup the master tree */
- }
- }
- }
- eina_array_flush(&o->glyphs_cleanup);
-
- free(o->master);
- free(o->glyphs);
- free(o->master_used);
- free(o->glyphs_used);
-
o->magic = 0;
}
}
static void
-evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row, int x, int w, int r, int g, int b, int a)
+evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row,
+ int x, int w,
+ int r, int g, int b, int a)
{
row->rects_num++;
if (row->rects_num > row->rects_alloc)
}
static void
-evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row, Evas_Object *eo_obj, Evas_Textgrid_Data *o, int x, Eina_Unicode codepoint, int r, int g, int b, int a)
+evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row,
+ Evas_Object_Protected_Data *obj,
+ Evas_Textgrid_Data *o,
+ int x,
+ Eina_Unicode codepoint,
+ int r, int g, int b, int a)
{
- unsigned int text_props_index;
+ Evas_Script_Type script;
+ Evas_Font_Instance *script_fi = NULL;
+ Evas_Font_Instance *cur_fi = NULL;
row->texts_num++;
if (row->texts_num > row->texts_alloc)
row->texts = t;
}
- text_props_index = evas_object_textgrid_textprop_ref(eo_obj, o, codepoint);
+ script = evas_common_language_script_type_get(&codepoint, 1);
+ ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi,
+ script, &codepoint, 1);
+ memset(&(row->texts[row->texts_num - 1].text_props), 0,
+ sizeof(Evas_Text_Props));
+ evas_common_text_props_script_set
+ (&(row->texts[row->texts_num - 1].text_props), script);
+ ENFN->font_text_props_info_create
+ (ENDT, script_fi, &codepoint,
+ &(row->texts[row->texts_num - 1].text_props), NULL, 0, 1,
+ EVAS_TEXT_PROPS_MODE_NONE,
+ o->cur.font_description->lang);
- row->texts[row->texts_num - 1].text_props_index = text_props_index;
row->texts[row->texts_num - 1].x = x;
row->texts[row->texts_num - 1].r = r;
row->texts[row->texts_num - 1].g = g;
}
static void
-evas_object_textgrid_render(Evas_Object *eo_obj,
+evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
Evas_Object_Protected_Data *obj,
void *type_private_data,
void *output, void *context, void *surface, int x, int y, Eina_Bool do_async)
if ((c) && (c->a > 0))
{
if (cells->codepoint > 0)
- evas_object_textgrid_row_text_append(row, eo_obj, o, xp,
+ evas_object_textgrid_row_text_append(row, obj,
+ o, xp,
cells->codepoint,
c->r, c->g, c->b, c->a);
// XXX: underlines and strikethroughs dont get
{
Evas_Text_Props *props;
- props = _textprop_from_idx(o, row->texts[xx].text_props_index);
+ props = &row->texts[xx].text_props;
evas_common_font_draw_prepare(props);
int tx = xp + row->texts[xx].x;
int ty = yp + o->ascent;
- props = _textprop_from_idx(o, row->texts[xx].text_props_index);
+ props = &row->texts[xx].text_props;
r = row->texts[xx].r;
g = row->texts[xx].g;
/* move cur to prev safely for object data */
evas_object_cur_prev(eo_obj);
o->prev = o->cur;
-
- while (eina_array_count(&o->glyphs_cleanup) > 0)
- {
- Evas_Text_Props *prop;
- unsigned int props_index;
-
- props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
- prop = _textprop_from_idx(o, props_index);
-
- evas_common_text_props_content_nofree_unref(prop);
- if (!prop->info)
- {
- o->glyphs_used[props_index >> 8]--;
-
- if (!o->glyphs_used[props_index >> 8])
- {
- /* FIXME: cleanup the master tree */
- }
- }
- }
}
static unsigned int
o->core_change = 1;
evas_object_textgrid_rows_clear(eo_obj);
evas_object_change(eo_obj, obj);
-
- /* Force destroy of all cached Evas_Text_Props */
- while (eina_array_count(&o->glyphs_cleanup) > 0)
- {
- Evas_Text_Props *prop;
- unsigned int props_index;
-
- props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
- prop = _textprop_from_idx(o, props_index);
-
- evas_common_text_props_content_nofree_unref(prop);
- if (!prop->info)
- {
- o->glyphs_used[props_index >> 8]--;
-
- if (!o->glyphs_used[props_index >> 8])
- {
- /* FIXME: cleanup the master tree */
- }
- }
- }
}
EOLIAN static void