summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_object_textgrid.c
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2015-09-02 20:50:31 +0200
committerBoris Faure <billiob@gmail.com>2016-03-12 18:10:03 +0100
commitf3dc094310d794435a9c7beceef760d1ea913a39 (patch)
tree9c74792762ecb9783b912be9c11cd9e7e33915a8 /src/lib/evas/canvas/evas_object_textgrid.c
parent437ba4c46d0c161bd11c6f6d42adbff872a8540a (diff)
evas_text_grid: remove optimisation (will come back later) to make code more readable
Diffstat (limited to '')
-rw-r--r--src/lib/evas/canvas/evas_object_textgrid.c332
1 files changed, 33 insertions, 299 deletions
diff --git a/src/lib/evas/canvas/evas_object_textgrid.c b/src/lib/evas/canvas/evas_object_textgrid.c
index 8742a4c2de..45aeab620b 100644
--- a/src/lib/evas/canvas/evas_object_textgrid.c
+++ b/src/lib/evas/canvas/evas_object_textgrid.c
@@ -21,18 +21,6 @@ typedef struct _Evas_Object_Textgrid_Row Evas_Object_Textgrid_Row;
21typedef struct _Evas_Object_Textgrid_Rect Evas_Object_Textgrid_Rect; 21typedef struct _Evas_Object_Textgrid_Rect Evas_Object_Textgrid_Rect;
22typedef struct _Evas_Object_Textgrid_Text Evas_Object_Textgrid_Text; 22typedef struct _Evas_Object_Textgrid_Text Evas_Object_Textgrid_Text;
23typedef struct _Evas_Object_Textgrid_Line Evas_Object_Textgrid_Line; 23typedef struct _Evas_Object_Textgrid_Line Evas_Object_Textgrid_Line;
24typedef struct _Evas_Textgrid_Hash_Master Evas_Textgrid_Hash_Master;
25typedef struct _Evas_Textgrid_Hash_Glyphs Evas_Textgrid_Hash_Glyphs;
26
27struct _Evas_Textgrid_Hash_Master
28{
29 int next[16];
30};
31
32struct _Evas_Textgrid_Hash_Glyphs
33{
34 Evas_Text_Props props[256];
35};
36 24
37struct _Evas_Textgrid_Data 25struct _Evas_Textgrid_Data
38{ 26{
@@ -58,18 +46,6 @@ struct _Evas_Textgrid_Data
58 46
59 Evas_Font_Set *font; 47 Evas_Font_Set *font;
60 48
61 Evas_Textgrid_Hash_Master *master;
62 Evas_Textgrid_Hash_Glyphs *glyphs;
63 unsigned char *master_used;
64 unsigned char *glyphs_used;
65 unsigned int master_length;
66 unsigned int glyphs_length;
67
68 unsigned int last_mask;
69 Evas_Textgrid_Hash_Glyphs *last_glyphs;
70
71 Eina_Array glyphs_cleanup;
72
73 unsigned int changed : 1; 49 unsigned int changed : 1;
74 unsigned int core_change : 1; 50 unsigned int core_change : 1;
75 unsigned int row_change : 1; 51 unsigned int row_change : 1;
@@ -101,7 +77,7 @@ struct _Evas_Object_Textgrid_Text
101{ 77{
102 unsigned char r, g, b, a; 78 unsigned char r, g, b, a;
103 int x; 79 int x;
104 unsigned int text_props_index; 80 Evas_Text_Props text_props;
105}; 81};
106 82
107struct _Evas_Object_Textgrid_Line 83struct _Evas_Object_Textgrid_Line
@@ -166,197 +142,6 @@ static const Evas_Object_Func object_func =
166 NULL 142 NULL
167}; 143};
168 144
169/* almost generic private array data type */
170static int
171evas_object_textgrid_textprop_get(Evas_Object *eo_obj, Evas_Textgrid_Data *o, Eina_Unicode codepoint,
172 unsigned int glyphs_index, unsigned char *used)
173{
174 Evas_Textgrid_Hash_Glyphs *glyph;
175 unsigned char idx = codepoint & 0xFF;
176
177 glyph = &(o->glyphs[glyphs_index]);
178
179 if (!glyph->props[idx].info)
180 {
181 Evas_Font_Instance *script_fi = NULL;
182 Evas_Font_Instance *cur_fi = NULL;
183 Evas_Script_Type script;
184
185 script = evas_common_language_script_type_get(&codepoint, 1);
186 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
187 ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi, script, &codepoint, 1);
188 memset(&(glyph->props[idx]), 0, sizeof(Evas_Text_Props));
189 evas_common_text_props_script_set(&(glyph->props[idx]), script);
190 ENFN->font_text_props_info_create(ENDT, script_fi, &codepoint,
191 &(glyph->props[idx]), NULL, 0, 1,
192 EVAS_TEXT_PROPS_MODE_NONE,
193 o->cur.font_description->lang);
194 (*used)++;
195 }
196 else
197 {
198 evas_common_text_props_content_ref(&(glyph->props[idx]));
199 }
200
201 return glyphs_index << 8 | (unsigned int) idx;
202}
203
204static int
205evas_object_textgrid_textprop_ref(Evas_Object *eo_obj, Evas_Textgrid_Data *o, Eina_Unicode codepoint)
206{
207 unsigned int mask = 0xF0000000;
208 unsigned int shift = 28;
209 unsigned int offset = 0;
210 unsigned int glyphs_index;
211
212 if (o->last_glyphs)
213 {
214 if ((o->last_mask) && ((o->last_mask & codepoint) == o->last_mask))
215 goto end;
216 }
217
218 if (!o->master)
219 {
220 o->master = calloc(6, sizeof (Evas_Textgrid_Hash_Master));
221 o->master_used = calloc(6, sizeof (unsigned char));
222 o->glyphs = calloc(1, sizeof (Evas_Textgrid_Hash_Glyphs));
223 o->glyphs_used = calloc(1, sizeof (unsigned char));
224 if (!o->master || !o->master_used || !o->glyphs || !o->glyphs_used)
225 {
226 free(o->master);
227 o->master = NULL;
228 free(o->master_used);
229 o->master_used = NULL;
230 free(o->glyphs);
231 o->glyphs = NULL;
232 free(o->glyphs_used);
233 o->glyphs_used = NULL;
234 return 0xFFFFFFFF;
235 }
236
237 while (shift > 8)
238 {
239 o->master[offset].next[(mask & codepoint) >> shift] = offset + 1;
240 o->master_used[offset] = 1;
241 offset++;
242 shift -= 4;
243 mask >>= 4;
244 }
245
246 o->glyphs_length = 1;
247 o->master_length = 6;
248 o->master[5].next[(codepoint & 0xF00) >> 8] = 0xFF000000;
249 o->last_glyphs = o->glyphs;
250 o->last_mask = codepoint & 0xFFFFFF00;
251
252 goto end;
253 }
254
255 while ((shift > 8)
256 && (o->master[offset].next[(codepoint & mask) >> shift] != 0))
257 {
258 offset = o->master[offset].next[(codepoint & mask) >> shift];
259 mask >>= 4;
260 shift -= 4;
261 }
262
263 if (shift > 8)
264 {
265 Evas_Textgrid_Hash_Master *tmp;
266 unsigned char *tmp_used;
267 int master_count;
268 int count;
269 int end;
270
271 count = (shift - 8) / 4;
272 master_count = o->master_length + count;
273
274 /* FIXME: find empty entry */
275 tmp = realloc(o->master, master_count * sizeof (Evas_Textgrid_Hash_Master));
276 if (!tmp) return 0xFFFFFFFF;
277 o->master = tmp;
278 tmp_used = realloc(o->master_used, master_count);
279 if (!tmp_used) return 0xFFFFFFFF;
280 o->master_used = tmp_used;
281
282 memset(o->master + o->master_length, 0, count * sizeof (Evas_Textgrid_Hash_Master));
283 memset(o->master_used + o->master_length, 1, count);
284 end = o->master_length;
285 o->master_length = master_count;
286
287 while (shift > 8)
288 {
289 o->master[offset].next[(mask & codepoint) >> shift] = end;
290 o->master_used[offset] = 1;
291 end++;
292 offset = end;
293 shift -= 4;
294 mask >>= 4;
295 }
296 offset--;
297 }
298 if ((o->master[offset].next[(codepoint & mask) >> shift] == 0)
299 || ((o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF) >= o->glyphs_length))
300 {
301 Evas_Textgrid_Hash_Glyphs *tmp;
302 unsigned char *tmp_used;
303 int count;
304
305 /* FIXME: find empty entry */
306 if (o->master[offset].next[(codepoint & mask) >> shift] == 0)
307 count = o->glyphs_length + 1;
308 else
309 count = (o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF) + 1;
310 tmp = realloc(o->glyphs, count * sizeof (Evas_Textgrid_Hash_Glyphs));
311 if (!tmp) return 0xFFFFFFFF;
312 o->glyphs = tmp;
313 tmp_used = realloc(o->glyphs_used, count * sizeof (unsigned char));
314 if (!tmp_used) return 0xFFFFFFFF;
315 o->glyphs_used = tmp_used;
316
317 // FIXME: What should we write when allocating more than one new entry?
318 o->master[offset].next[(codepoint & mask) >> shift] = o->glyphs_length + 0xFF000000;
319
320 memset(o->glyphs + o->glyphs_length, 0, (count - o->glyphs_length) * sizeof (Evas_Textgrid_Hash_Glyphs));
321 memset(o->glyphs_used, 0, (count - o->glyphs_length) * sizeof(o->glyphs_used[0]));
322 o->glyphs_length = count;
323 }
324
325 o->last_glyphs = o->glyphs + (o->master[offset].next[(codepoint & mask) >> shift] & 0xFFFFFF);
326 o->last_mask = codepoint & 0xFFFFFF00;
327
328 end:
329 glyphs_index = o->last_glyphs - o->glyphs;
330 return evas_object_textgrid_textprop_get(eo_obj, o, codepoint, glyphs_index,
331 &(o->glyphs_used[glyphs_index]));
332}
333
334static Evas_Text_Props *
335_textprop_from_idx(Evas_Textgrid_Data *o, unsigned int props_index)
336{
337 return &(o->glyphs[props_index >> 8].props[props_index & 0xFF]);
338}
339
340
341static void
342evas_object_textgrid_textprop_unref(Evas_Textgrid_Data *o, unsigned int props_index)
343{
344 Evas_Text_Props *props;
345
346 props = _textprop_from_idx(o, props_index);
347
348 if (props->info)
349 {
350 if (props->info->refcount == 1)
351 eina_array_push(&o->glyphs_cleanup,
352 (void *)((uintptr_t)props_index));
353 else
354 {
355 evas_common_text_props_content_nofree_unref(props);
356 }
357 }
358}
359
360/* all nice and private */ 145/* all nice and private */
361static void 146static void
362evas_object_textgrid_init(Evas_Object *eo_obj) 147evas_object_textgrid_init(Evas_Object *eo_obj)
@@ -372,11 +157,11 @@ evas_object_textgrid_init(Evas_Object *eo_obj)
372 o->prev = o->cur; 157 o->prev = o->cur;
373 eina_array_step_set(&o->cur.palette_standard, sizeof (Eina_Array), 16); 158 eina_array_step_set(&o->cur.palette_standard, sizeof (Eina_Array), 16);
374 eina_array_step_set(&o->cur.palette_extended, sizeof (Eina_Array), 16); 159 eina_array_step_set(&o->cur.palette_extended, sizeof (Eina_Array), 16);
375 eina_array_step_set(&o->glyphs_cleanup, sizeof (Eina_Array), 16);
376} 160}
377 161
378static void 162static void
379evas_object_textgrid_row_clear(Evas_Textgrid_Data *o, Evas_Object_Textgrid_Row *r) 163evas_object_textgrid_row_clear(Evas_Textgrid_Data *o EINA_UNUSED,
164 Evas_Object_Textgrid_Row *r)
380{ 165{
381 int i; 166 int i;
382 167
@@ -390,11 +175,7 @@ evas_object_textgrid_row_clear(Evas_Textgrid_Data *o, Evas_Object_Textgrid_Row *
390 if (r->texts) 175 if (r->texts)
391 { 176 {
392 for (i = 0; i < r->texts_num; i++) 177 for (i = 0; i < r->texts_num; i++)
393 if (r->texts[i].text_props_index != 0xFFFFFFFF) 178 evas_common_text_props_content_unref(&(r->texts[i].text_props));
394 {
395 evas_object_textgrid_textprop_unref(o, r->texts[i].text_props_index);
396 r->texts[i].text_props_index = 0xFFFFFFFF;
397 }
398 free(r->texts); 179 free(r->texts);
399 r->texts = NULL; 180 r->texts = NULL;
400 r->texts_num = 0; 181 r->texts_num = 0;
@@ -445,32 +226,6 @@ evas_object_textgrid_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
445 free(c); 226 free(c);
446 eina_array_flush(&o->cur.palette_extended); 227 eina_array_flush(&o->cur.palette_extended);
447 228
448 while (eina_array_count(&o->glyphs_cleanup) > 0)
449 {
450 Evas_Text_Props *prop;
451 unsigned int props_index;
452
453 props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
454 prop = &(o->glyphs[props_index >> 8].props[props_index & 0xFF]);
455
456 evas_common_text_props_content_nofree_unref(prop);
457 if (!prop->info)
458 {
459 o->glyphs_used[props_index >> 8]--;
460
461 if (!o->glyphs_used[props_index >> 8])
462 {
463 /* FIXME: cleanup the master tree */
464 }
465 }
466 }
467 eina_array_flush(&o->glyphs_cleanup);
468
469 free(o->master);
470 free(o->glyphs);
471 free(o->master_used);
472 free(o->glyphs_used);
473
474 o->magic = 0; 229 o->magic = 0;
475} 230}
476 231
@@ -484,7 +239,9 @@ _evas_textgrid_eo_base_destructor(Eo *eo_obj, Evas_Textgrid_Data *o EINA_UNUSED)
484} 239}
485 240
486static void 241static void
487evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row, int x, int w, int r, int g, int b, int a) 242evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row,
243 int x, int w,
244 int r, int g, int b, int a)
488{ 245{
489 row->rects_num++; 246 row->rects_num++;
490 if (row->rects_num > row->rects_alloc) 247 if (row->rects_num > row->rects_alloc)
@@ -509,9 +266,16 @@ evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row, int x, int w
509} 266}
510 267
511static void 268static void
512evas_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) 269evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row,
270 Evas_Object_Protected_Data *obj,
271 Evas_Textgrid_Data *o,
272 int x,
273 Eina_Unicode codepoint,
274 int r, int g, int b, int a)
513{ 275{
514 unsigned int text_props_index; 276 Evas_Script_Type script;
277 Evas_Font_Instance *script_fi = NULL;
278 Evas_Font_Instance *cur_fi = NULL;
515 279
516 row->texts_num++; 280 row->texts_num++;
517 if (row->texts_num > row->texts_alloc) 281 if (row->texts_num > row->texts_alloc)
@@ -528,9 +292,19 @@ evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row, Evas_Object
528 row->texts = t; 292 row->texts = t;
529 } 293 }
530 294
531 text_props_index = evas_object_textgrid_textprop_ref(eo_obj, o, codepoint); 295 script = evas_common_language_script_type_get(&codepoint, 1);
296 ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi,
297 script, &codepoint, 1);
298 memset(&(row->texts[row->texts_num - 1].text_props), 0,
299 sizeof(Evas_Text_Props));
300 evas_common_text_props_script_set
301 (&(row->texts[row->texts_num - 1].text_props), script);
302 ENFN->font_text_props_info_create
303 (ENDT, script_fi, &codepoint,
304 &(row->texts[row->texts_num - 1].text_props), NULL, 0, 1,
305 EVAS_TEXT_PROPS_MODE_NONE,
306 o->cur.font_description->lang);
532 307
533 row->texts[row->texts_num - 1].text_props_index = text_props_index;
534 row->texts[row->texts_num - 1].x = x; 308 row->texts[row->texts_num - 1].x = x;
535 row->texts[row->texts_num - 1].r = r; 309 row->texts[row->texts_num - 1].r = r;
536 row->texts[row->texts_num - 1].g = g; 310 row->texts[row->texts_num - 1].g = g;
@@ -577,7 +351,7 @@ _drop_glyphs_ref(const void *container EINA_UNUSED, void *data, void *fdata)
577} 351}
578 352
579static void 353static void
580evas_object_textgrid_render(Evas_Object *eo_obj, 354evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
581 Evas_Object_Protected_Data *obj, 355 Evas_Object_Protected_Data *obj,
582 void *type_private_data, 356 void *type_private_data,
583 void *output, void *context, void *surface, int x, int y, Eina_Bool do_async) 357 void *output, void *context, void *surface, int x, int y, Eina_Bool do_async)
@@ -662,7 +436,8 @@ evas_object_textgrid_render(Evas_Object *eo_obj,
662 if ((c) && (c->a > 0)) 436 if ((c) && (c->a > 0))
663 { 437 {
664 if (cells->codepoint > 0) 438 if (cells->codepoint > 0)
665 evas_object_textgrid_row_text_append(row, eo_obj, o, xp, 439 evas_object_textgrid_row_text_append(row, obj,
440 o, xp,
666 cells->codepoint, 441 cells->codepoint,
667 c->r, c->g, c->b, c->a); 442 c->r, c->g, c->b, c->a);
668 // XXX: underlines and strikethroughs dont get 443 // XXX: underlines and strikethroughs dont get
@@ -729,7 +504,7 @@ evas_object_textgrid_render(Evas_Object *eo_obj,
729 { 504 {
730 Evas_Text_Props *props; 505 Evas_Text_Props *props;
731 506
732 props = _textprop_from_idx(o, row->texts[xx].text_props_index); 507 props = &row->texts[xx].text_props;
733 508
734 evas_common_font_draw_prepare(props); 509 evas_common_font_draw_prepare(props);
735 510
@@ -770,7 +545,7 @@ evas_object_textgrid_render(Evas_Object *eo_obj,
770 int tx = xp + row->texts[xx].x; 545 int tx = xp + row->texts[xx].x;
771 int ty = yp + o->ascent; 546 int ty = yp + o->ascent;
772 547
773 props = _textprop_from_idx(o, row->texts[xx].text_props_index); 548 props = &row->texts[xx].text_props;
774 549
775 r = row->texts[xx].r; 550 r = row->texts[xx].r;
776 g = row->texts[xx].g; 551 g = row->texts[xx].g;
@@ -960,26 +735,6 @@ evas_object_textgrid_render_post(Evas_Object *eo_obj,
960 /* move cur to prev safely for object data */ 735 /* move cur to prev safely for object data */
961 evas_object_cur_prev(eo_obj); 736 evas_object_cur_prev(eo_obj);
962 o->prev = o->cur; 737 o->prev = o->cur;
963
964 while (eina_array_count(&o->glyphs_cleanup) > 0)
965 {
966 Evas_Text_Props *prop;
967 unsigned int props_index;
968
969 props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
970 prop = _textprop_from_idx(o, props_index);
971
972 evas_common_text_props_content_nofree_unref(prop);
973 if (!prop->info)
974 {
975 o->glyphs_used[props_index >> 8]--;
976
977 if (!o->glyphs_used[props_index >> 8])
978 {
979 /* FIXME: cleanup the master tree */
980 }
981 }
982 }
983} 738}
984 739
985static unsigned int 740static unsigned int
@@ -1263,27 +1018,6 @@ _evas_textgrid_efl_text_properties_font_set(Eo *eo_obj, Evas_Textgrid_Data *o, c
1263 o->core_change = 1; 1018 o->core_change = 1;
1264 evas_object_textgrid_rows_clear(eo_obj); 1019 evas_object_textgrid_rows_clear(eo_obj);
1265 evas_object_change(eo_obj, obj); 1020 evas_object_change(eo_obj, obj);
1266
1267 /* Force destroy of all cached Evas_Text_Props */
1268 while (eina_array_count(&o->glyphs_cleanup) > 0)
1269 {
1270 Evas_Text_Props *prop;
1271 unsigned int props_index;
1272
1273 props_index = (unsigned int) (intptr_t) eina_array_pop(&o->glyphs_cleanup);
1274 prop = _textprop_from_idx(o, props_index);
1275
1276 evas_common_text_props_content_nofree_unref(prop);
1277 if (!prop->info)
1278 {
1279 o->glyphs_used[props_index >> 8]--;
1280
1281 if (!o->glyphs_used[props_index >> 8])
1282 {
1283 /* FIXME: cleanup the master tree */
1284 }
1285 }
1286 }
1287} 1021}
1288 1022
1289EOLIAN static void 1023EOLIAN static void