1 #include "evas_common_private.h" /* Includes evas_bidi_utils stuff. */
2 #include "evas_private.h"
3
4 #define MY_CLASS EVAS_TEXTGRID_CLASS
5
6 #define MY_CLASS_NAME "Evas_Textgrid"
7
8 /* private magic number for text objects */
9 static const char o_type[] = "textgrid";
10
11 /* private struct for line object internal data */
12 typedef struct _Evas_Textgrid_Data Evas_Textgrid_Data;
13 typedef struct _Evas_Object_Textgrid_Cell Evas_Object_Textgrid_Cell;
14 typedef struct _Evas_Object_Textgrid_Color Evas_Object_Textgrid_Color;
15
16 typedef struct _Evas_Object_Textgrid_Row Evas_Object_Textgrid_Row;
17 typedef struct _Evas_Object_Textgrid_Rect Evas_Object_Textgrid_Rect;
18 typedef struct _Evas_Object_Textgrid_Text Evas_Object_Textgrid_Text;
19 typedef struct _Evas_Object_Textgrid_Line Evas_Object_Textgrid_Line;
20
21 struct _Evas_Textgrid_Data
22 {
23 struct {
24 int w, h;
25 int char_width;
26 int char_height;
27 Evas_Object_Textgrid_Row *rows;
28 Evas_Textgrid_Cell *cells;
29
30 const char *font_source;
31 const char *font_name;
32 Evas_Font_Size font_size;
33 Evas_Font_Description *font_description_normal;
34
35 Eina_Array palette_standard;
36 Eina_Array palette_extended;
37 Efl_Text_Font_Bitmap_Scalable bitmap_scalable;
38 } cur, prev;
39
40 int ascent;
41
42 Evas_Font_Set *font_normal;
43 Evas_Font_Set *font_bold;
44 Evas_Font_Set *font_italic;
45 Evas_Font_Set *font_bolditalic;
46
47 unsigned int changed : 1;
48 unsigned int core_change : 1;
49 unsigned int row_change : 1;
50 unsigned int pal_change : 1;
51 };
52
53 struct _Evas_Object_Textgrid_Color
54 {
55 unsigned char r, g, b, a;
56 };
57
58 struct _Evas_Object_Textgrid_Row
59 {
60 int ch1, ch2; // change region, -1 == none
61 int rects_num, texts_num, lines_num;
62 int rects_alloc, texts_alloc, lines_alloc;
63 Evas_Object_Textgrid_Rect *rects; // rects + colors
64 Evas_Object_Textgrid_Text *texts; // text
65 Evas_Object_Textgrid_Line *lines; // underlines, strikethroughs
66 };
67
68 struct _Evas_Object_Textgrid_Rect
69 {
70 unsigned char r, g, b, a;
71 int x, w;
72 };
73
74 struct _Evas_Object_Textgrid_Text
75 {
76 Evas_Text_Props text_props;
77 unsigned char r, g, b, a;
78 int x : 30;
79 unsigned char bold : 1;
80 unsigned char italic : 1;
81 };
82
83 struct _Evas_Object_Textgrid_Line
84 {
85 unsigned char r, g, b, a;
86 int x, w, y;
87 };
88
89 /* private methods for textgrid objects */
90 static void evas_object_textgrid_init(Evas_Object *eo_obj);
91 static void evas_object_textgrid_render(Evas_Object *eo_obj,
92 Evas_Object_Protected_Data *obj,
93 void *type_private_data,
94 void *engine, void *output, void *context, void *surface,
95 int x, int y, Eina_Bool do_async);
96 static void evas_object_textgrid_render_pre(Evas_Object *eo_obj,
97 Evas_Object_Protected_Data *obj,
98 void *type_private_data);
99 static void evas_object_textgrid_render_post(Evas_Object *eo_obj,
100 Evas_Object_Protected_Data *obj,
101 void *type_private_data);
102
103 static void *evas_object_textgrid_engine_data_get(Evas_Object *eo_obj);
104
105 static int evas_object_textgrid_is_opaque(Evas_Object *eo_obj,
106 Evas_Object_Protected_Data *obj,
107 void *type_private_data);
108 static int evas_object_textgrid_was_opaque(Evas_Object *eo_obj,
109 Evas_Object_Protected_Data *obj,
110 void *type_private_data);
111
112 static const Evas_Object_Func object_func =
113 {
114 /* methods (compulsory) */
115 NULL,
116 evas_object_textgrid_render,
117 evas_object_textgrid_render_pre,
118 evas_object_textgrid_render_post,
119 evas_object_textgrid_engine_data_get,
120 /* these are optional. NULL = nothing */
121 NULL,
122 NULL,
123 evas_object_textgrid_is_opaque,
124 evas_object_textgrid_was_opaque,
125 NULL,
126 NULL,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 NULL // render_prepare
132 };
133
134 /* all nice and private */
135 static void
evas_object_textgrid_init(Evas_Object * eo_obj)136 evas_object_textgrid_init(Evas_Object *eo_obj)
137 {
138 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
139 /* set up methods (compulsory) */
140 obj->func = &object_func;
141 obj->private_data = efl_data_ref(eo_obj, MY_CLASS);
142 obj->type = o_type;
143
144 Evas_Textgrid_Data *o = obj->private_data;
145 o->prev.bitmap_scalable = o->cur.bitmap_scalable = EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR;
146 o->prev = o->cur;
147 eina_array_step_set(&o->cur.palette_standard, sizeof (Eina_Array), 16);
148 eina_array_step_set(&o->cur.palette_extended, sizeof (Eina_Array), 16);
149 }
150
151 static void
evas_object_textgrid_row_clear(Evas_Textgrid_Data * o EINA_UNUSED,Evas_Object_Textgrid_Row * r)152 evas_object_textgrid_row_clear(Evas_Textgrid_Data *o EINA_UNUSED,
153 Evas_Object_Textgrid_Row *r)
154 {
155 int i;
156
157 if (r->rects)
158 {
159 free(r->rects);
160 r->rects = NULL;
161 r->rects_num = 0;
162 r->rects_alloc = 0;
163 }
164 if (r->texts)
165 {
166 for (i = 0; i < r->texts_num; i++)
167 evas_common_text_props_content_unref(&(r->texts[i].text_props));
168 free(r->texts);
169 r->texts = NULL;
170 r->texts_num = 0;
171 r->texts_alloc = 0;
172 }
173 if (r->lines)
174 {
175 free(r->lines);
176 r->lines = NULL;
177 r->lines_num = 0;
178 r->lines_alloc = 0;
179 }
180 }
181
182 static void
evas_object_textgrid_rows_clear(Evas_Object * eo_obj)183 evas_object_textgrid_rows_clear(Evas_Object *eo_obj)
184 {
185 int i;
186
187 Evas_Textgrid_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
188 if (!o->cur.rows) return;
189 for (i = 0; i < o->cur.h; i++)
190 {
191 evas_object_textgrid_row_clear(o, &(o->cur.rows[i]));
192 o->cur.rows[i].ch1 = 0;
193 o->cur.rows[i].ch2 = o->cur.w - 1;
194 }
195 }
196
197 static void
evas_object_textgrid_free(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj EINA_UNUSED)198 evas_object_textgrid_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj EINA_UNUSED)
199 {
200 Evas_Object_Textgrid_Color *c;
201 Evas_Textgrid_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
202
203 /* free obj */
204 evas_object_textgrid_rows_clear(eo_obj);
205 if (o->cur.rows) free(o->cur.rows);
206 if (o->cur.font_name) eina_stringshare_del(o->cur.font_name);
207 if (o->cur.font_source) eina_stringshare_del(o->cur.font_source);
208
209 if (o->cur.font_description_normal)
210 evas_font_desc_unref(o->cur.font_description_normal);
211 if (o->font_normal) evas_font_free(o->font_normal);
212 if (o->font_bold) evas_font_free(o->font_bold);
213 if (o->font_italic) evas_font_free(o->font_italic);
214 if (o->font_bolditalic) evas_font_free(o->font_bolditalic);
215
216 if (o->cur.cells) free(o->cur.cells);
217 while ((c = eina_array_pop(&o->cur.palette_standard)))
218 free(c);
219 eina_array_flush(&o->cur.palette_standard);
220 while ((c = eina_array_pop(&o->cur.palette_extended)))
221 free(c);
222 eina_array_flush(&o->cur.palette_extended);
223 }
224
225 EOLIAN static void
_evas_textgrid_efl_object_destructor(Eo * eo_obj,Evas_Textgrid_Data * o EINA_UNUSED)226 _evas_textgrid_efl_object_destructor(Eo *eo_obj, Evas_Textgrid_Data *o EINA_UNUSED)
227 {
228 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
229 evas_object_textgrid_free(eo_obj, obj);
230 efl_data_unref(eo_obj, obj->private_data);
231 efl_destructor(efl_super(eo_obj, MY_CLASS));
232 }
233
234 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)235 evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row,
236 int x, int w,
237 int r, int g, int b, int a)
238 {
239 row->rects_num++;
240 if (row->rects_num > row->rects_alloc)
241 {
242 Evas_Object_Textgrid_Rect *t;
243
244 row->rects_alloc += 8; // dont expect many rects per line
245 t = realloc(row->rects, sizeof(Evas_Object_Textgrid_Rect) * row->rects_alloc);
246 if (!t)
247 {
248 row->rects_num--;
249 return;
250 }
251 row->rects = t;
252 }
253 row->rects[row->rects_num - 1].x = x;
254 row->rects[row->rects_num - 1].w = w;
255 row->rects[row->rects_num - 1].r = r;
256 row->rects[row->rects_num - 1].g = g;
257 row->rects[row->rects_num - 1].b = b;
258 row->rects[row->rects_num - 1].a = a;
259 }
260
261 static Evas_Font_Set *
_textgrid_font_get(Evas_Textgrid_Data * o,Eina_Bool is_bold,Eina_Bool is_italic)262 _textgrid_font_get(Evas_Textgrid_Data *o,
263 Eina_Bool is_bold,
264 Eina_Bool is_italic)
265 {
266 if ((!is_bold) && (!is_italic))
267 return o->font_normal;
268 /* bold */
269 else if ((is_bold) && (!is_italic))
270 {
271 if (o->font_bold)
272 return o->font_bold;
273 else
274 return o->font_normal;
275 }
276 /* italic */
277 else if ((!is_bold) && (is_italic))
278 {
279 if (o->font_italic)
280 return o->font_italic;
281 else
282 return o->font_normal;
283 }
284 /* bolditalic */
285 else
286 {
287 if (o->font_bolditalic)
288 return o->font_bolditalic;
289 else if (o->font_italic)
290 return o->font_italic;
291 else if (o->font_bold)
292 return o->font_bold;
293 else
294 return o->font_normal;
295 }
296 }
297
298 static void
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,Eina_Bool is_bold,Eina_Bool is_italic)299 evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row,
300 Evas_Object_Protected_Data *obj,
301 Evas_Textgrid_Data *o,
302 int x,
303 Eina_Unicode codepoint,
304 int r, int g, int b, int a,
305 Eina_Bool is_bold,
306 Eina_Bool is_italic)
307 {
308 Evas_Script_Type script;
309 Evas_Font_Instance *script_fi = NULL;
310 Evas_Font_Instance *cur_fi = NULL;
311 Evas_Object_Textgrid_Text *text;
312 Evas_Font_Set *font;
313
314 row->texts_num++;
315 if (row->texts_num > row->texts_alloc)
316 {
317 Evas_Object_Textgrid_Text *t;
318
319 row->texts_alloc += 32; // expect more text per line
320 t = realloc(row->texts, sizeof(Evas_Object_Textgrid_Text) * row->texts_alloc);
321 if (!t)
322 {
323 row->texts_num--;
324 return;
325 }
326 row->texts = t;
327 }
328
329 script = evas_common_language_script_type_get(&codepoint, 1);
330 text = &row->texts[row->texts_num - 1];
331 text->bold = is_bold;
332 text->italic = is_italic;
333 font = _textgrid_font_get(o, is_bold, is_italic);
334 ENFN->font_run_end_get(ENC, font, &script_fi, &cur_fi,
335 script, &codepoint, 1);
336 memset(&(text->text_props), 0, sizeof(Evas_Text_Props));
337 evas_common_text_props_script_set(&(text->text_props), script);
338 ENFN->font_text_props_info_create(ENC, cur_fi, &codepoint,
339 &(text->text_props), NULL, 0, 1,
340 EVAS_TEXT_PROPS_MODE_NONE,
341 o->cur.font_description_normal->lang);
342
343 text->x = x;
344 text->r = r;
345 text->g = g;
346 text->b = b;
347 text->a = a;
348 }
349
350 static void
evas_object_textgrid_row_line_append(Evas_Object_Textgrid_Row * row,int x,int w,int y,int r,int g,int b,int a)351 evas_object_textgrid_row_line_append(Evas_Object_Textgrid_Row *row, int x, int w, int y, int r, int g, int b, int a)
352 {
353 row->lines_num++;
354 if (row->lines_num > row->lines_alloc)
355 {
356 Evas_Object_Textgrid_Line *t;
357
358 row->lines_alloc += 8; // dont expect many lines per line
359 t = realloc(row->lines, sizeof(Evas_Object_Textgrid_Line) * row->lines_alloc);
360 if (!t)
361 {
362 row->lines_num--;
363 return;
364 }
365 row->lines = t;
366 }
367 row->lines[row->lines_num - 1].x = x;
368 row->lines[row->lines_num - 1].w = w;
369 row->lines[row->lines_num - 1].y = y;
370 row->lines[row->lines_num - 1].r = r;
371 row->lines[row->lines_num - 1].g = g;
372 row->lines[row->lines_num - 1].b = b;
373 row->lines[row->lines_num - 1].a = a;
374 }
375
376 static Eina_Bool
_drop_glyphs_ref(const void * container EINA_UNUSED,void * data,void * fdata)377 _drop_glyphs_ref(const void *container EINA_UNUSED, void *data, void *fdata)
378 {
379 Evas_Font_Array_Data *fad = data;
380 Evas_Public_Data *pd = fdata;
381
382 evas_common_font_glyphs_unref(fad->glyphs);
383 eina_array_pop(&pd->glyph_unref_queue);
384
385 return EINA_TRUE;
386 }
387
388 static void
evas_object_textgrid_render(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,void * type_private_data,void * engine,void * output,void * context,void * surface,int x,int y,Eina_Bool do_async)389 evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
390 Evas_Object_Protected_Data *obj,
391 void *type_private_data,
392 void *engine, void *output, void *context, void *surface,
393 int x, int y, Eina_Bool do_async)
394 {
395 Evas_Textgrid_Cell *cells;
396 Evas_Object_Textgrid_Color *c;
397 Eina_Array *palette;
398 int xx, yy, xp, yp, w, h, ww, hh;
399 int rr = 0, rg = 0, rb = 0, ra = 0, rx = 0, rw = 0, run;
400
401 /* render object to surface with context, and offset by x,y */
402 Evas_Textgrid_Data *o = type_private_data;
403 ENFN->context_multiplier_unset(engine, context);
404 ENFN->context_render_op_set(engine, context, obj->cur->render_op);
405
406 if (!(o->font_normal) || (!o->cur.cells)) return;
407
408 w = o->cur.char_width;
409 h = o->cur.char_height;
410 ww = obj->cur->geometry.w;
411 hh = obj->cur->geometry.h;
412
413 // generate row data from cells (and only deal with rows that updated)
414 for (yy = 0, cells = o->cur.cells; yy < o->cur.h; yy++)
415 {
416 Evas_Object_Textgrid_Row *row = &(o->cur.rows[yy]);
417
418 if (row->ch1 < 0)
419 {
420 cells += o->cur.w;
421 continue;
422 }
423 row->ch1 = -1;
424 row->ch2 = 0;
425 run = 0;
426 xp = 0;
427 for (xx = 0; xx < o->cur.w; xx++, cells++)
428 {
429 if (cells->bg_extended) palette = &(o->cur.palette_extended);
430 else palette = &(o->cur.palette_standard);
431 if (cells->bg >= eina_array_count(palette)) c = NULL;
432 else c = eina_array_data_get(palette, cells->bg);
433 if ((c) && (c->a > 0))
434 {
435 if (!run)
436 {
437 run = 1;
438 rr = c->r;
439 rg = c->g;
440 rb = c->b;
441 ra = c->a;
442 rx = xp;
443 rw = w;
444 }
445 else if ((c->r != rr) || (c->g != rg) ||
446 (c->b != rb) || (c->a != ra))
447 {
448 evas_object_textgrid_row_rect_append(row, rx, rw,
449 rr, rg, rb, ra);
450 rr = c->r;
451 rg = c->g;
452 rb = c->b;
453 ra = c->a;
454 rx = xp;
455 rw = w;
456 }
457 else rw += w;
458 }
459 else if (run)
460 {
461 run = 0;
462 evas_object_textgrid_row_rect_append(row, rx, rw,
463 rr, rg, rb, ra);
464 }
465 if ((cells->codepoint > 0) || (cells->underline) ||
466 (cells->strikethrough))
467 {
468 if (cells->fg_extended) palette = &(o->cur.palette_extended);
469 else palette = &(o->cur.palette_standard);
470 if (cells->fg >= eina_array_count(palette)) c = NULL;
471 else c = eina_array_data_get(palette, cells->fg);
472 if ((c) && (c->a > 0))
473 {
474 if (cells->codepoint > 0)
475 evas_object_textgrid_row_text_append(row, obj,
476 o, xp,
477 cells->codepoint,
478 c->r, c->g, c->b, c->a,
479 cells->bold,
480 cells->italic);
481 // XXX: underlines and strikethroughs don't get
482 // merged into horizontal runs like bg rects above
483 if (cells->underline)
484 evas_object_textgrid_row_line_append(row, xp, w,
485 o->ascent + 1,
486 c->r, c->g, c->b, c->a);
487 if (cells->strikethrough)
488 evas_object_textgrid_row_line_append(row, xp, w,
489 ((3 * o->ascent) / 4),
490 c->r, c->g, c->b, c->a);
491 }
492 }
493 xp += w;
494 }
495 if (run)
496 {
497 run = 0;
498 evas_object_textgrid_row_rect_append(row, rx, rw,
499 rr, rg, rb, ra);
500 }
501 }
502 yp = obj->cur->geometry.y + y;
503 // draw the row data that is generated from the cell array
504 for (yy = 0, cells = o->cur.cells; yy < o->cur.h; yy++)
505 {
506 Evas_Object_Textgrid_Row *row = &(o->cur.rows[yy]);
507 Evas_Font_Array *texts;
508
509 xp = obj->cur->geometry.x + x;
510 for (xx = 0; xx < row->rects_num; xx++)
511 {
512 ENFN->context_color_set(engine, context,
513 row->rects[xx].r, row->rects[xx].g,
514 row->rects[xx].b, row->rects[xx].a);
515 ENFN->context_cutout_target(engine, context,
516 xp + row->rects[xx].x, yp,
517 row->rects[xx].w, h);
518 ENFN->rectangle_draw(engine, output, context, surface,
519 xp + row->rects[xx].x, yp,
520 row->rects[xx].w, h,
521 do_async);
522 }
523
524 if (row->texts_num)
525 {
526 if ((do_async) && (ENFN->multi_font_draw))
527 {
528 Evas_Font_Set *font, *current_font;
529 Eina_Bool async_unref;
530 Evas_Object_Textgrid_Text *text;
531
532 xx = 0;
533 do
534 {
535 texts = malloc(sizeof(*texts));
536 if (!texts)
537 {
538 ERR("Failed to allocate Evas_Font_Array.");
539 return;
540 }
541 texts->array = eina_inarray_new(sizeof(Evas_Font_Array_Data), 1);
542 texts->refcount = 1;
543
544 text = &row->texts[xx];
545 font = _textgrid_font_get(o, text->bold, text->italic);
546
547 do
548 {
549 Evas_Font_Array_Data *fad;
550 Evas_Text_Props *props;
551
552 current_font = font;
553
554 props = &text->text_props;
555 evas_common_font_draw_prepare(props);
556
557 evas_common_font_glyphs_ref(props->glyphs);
558 evas_unref_queue_glyph_put(obj->layer->evas,
559 props->glyphs);
560
561 fad = eina_inarray_grow(texts->array, 1);
562 if (!fad)
563 {
564 ERR("Failed to allocate Evas_Font_Array_Data.");
565 eina_inarray_free(texts->array);
566 free(texts);
567 return;
568 }
569 fad->color.r = text->r;
570 fad->color.g = text->g;
571 fad->color.b = text->b;
572 fad->color.a = text->a;
573 fad->x = text->x;
574 fad->glyphs = props->glyphs;
575
576 fad++;
577
578 xx++;
579 if (xx >= row->texts_num)
580 break;
581 text = &row->texts[xx];
582 font = _textgrid_font_get(o, text->bold,
583 text->italic);
584 }
585 while (font == current_font);
586
587 ENFN->context_cutout_target(engine, context,
588 xp - w, yp + o->ascent - h,
589 w * 3, h * 3);
590 async_unref =
591 ENFN->multi_font_draw(engine, output, context, surface,
592 current_font,
593 xp,
594 yp + o->ascent,
595 ww, hh, ww, hh, texts, do_async);
596 if (async_unref)
597 evas_unref_queue_texts_put(obj->layer->evas, texts);
598 else
599 {
600 eina_inarray_foreach(texts->array, _drop_glyphs_ref,
601 obj->layer->evas);
602 eina_inarray_free(texts->array);
603 free(texts);
604 }
605 }
606 while (xx < row->texts_num);
607 }
608 else
609 {
610 for (xx = 0; xx < row->texts_num; xx++)
611 {
612 Evas_Text_Props *props;
613 unsigned int r, g, b, a;
614 Evas_Object_Textgrid_Text *text = &row->texts[xx];
615 int tx = xp + text->x;
616 int ty = yp + o->ascent;
617 Evas_Font_Set *font;
618
619 props = &text->text_props;
620
621 r = text->r;
622 g = text->g;
623 b = text->b;
624 a = text->a;
625
626 ENFN->context_color_set(engine, context,
627 r, g, b, a);
628 font = _textgrid_font_get(o, text->bold, text->italic);
629 ENFN->context_cutout_target(engine, context,
630 tx - w, ty - h,
631 w * 3, h * 3);
632 evas_font_draw_async_check(obj, engine, output, context, surface,
633 font, tx, ty, ww, hh,
634 ww, hh, props, do_async);
635 }
636 }
637 }
638
639 for (xx = 0; xx < row->lines_num; xx++)
640 {
641 ENFN->context_color_set(engine, context,
642 row->lines[xx].r, row->lines[xx].g,
643 row->lines[xx].b, row->lines[xx].a);
644 ENFN->context_cutout_target(engine, context,
645 xp + row->lines[xx].x, yp + row->lines[xx].y,
646 row->lines[xx].w, 1);
647 ENFN->rectangle_draw(engine, output, context, surface,
648 xp + row->lines[xx].x, yp + row->lines[xx].y,
649 row->lines[xx].w, 1,
650 do_async);
651 }
652 yp += h;
653 }
654 }
655
656 static void
evas_object_textgrid_render_pre(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,void * type_private_data)657 evas_object_textgrid_render_pre(Evas_Object *eo_obj,
658 Evas_Object_Protected_Data *obj,
659 void *type_private_data)
660 {
661 int is_v, was_v;
662 Evas_Textgrid_Data *o = type_private_data;
663
664 /* don't pre-render the obj twice! */
665 if (obj->pre_render_done) return;
666 obj->pre_render_done = EINA_TRUE;
667 /* pre-render phase. This does anything an object needs to do just before */
668 /* rendering. That could mean loading the image data, retrieving it from */
669 /* elsewhere, decoding video, etc. */
670 /* When this is done the object needs to figure if it changed and */
671 /* if so what and where and add the appropriate redraw rectangles */
672
673 /* if someone is clipping this obj - go calculate the clipper */
674 if (obj->cur->clipper)
675 {
676 if (obj->cur->cache.clip.dirty)
677 evas_object_clip_recalc(obj->cur->clipper);
678 obj->cur->clipper->func->render_pre(obj->cur->clipper->object,
679 obj->cur->clipper,
680 obj->cur->clipper->private_data);
681 }
682 /* now figure what changed and add draw rects */
683 /* if it just became visible or invisible */
684 is_v = evas_object_is_visible(obj);
685 was_v = evas_object_was_visible(obj);
686 if (is_v != was_v)
687 {
688 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, eo_obj, is_v, was_v);
689 goto done;
690 }
691 if (obj->changed_map || obj->changed_src_visible)
692 {
693 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
694 eo_obj, obj);
695 goto done;
696 }
697 /* its not visible - we accounted for it appearing or not so just abort */
698 if (!is_v) goto done;
699 /* clipper changed this is in addition to anything else for obj */
700 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, eo_obj);
701 /* if we restacked (layer or just within a layer) and don't clip anyone */
702 if (obj->restack)
703 {
704 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
705 goto done;
706 }
707 /* if it changed color */
708 if ((obj->cur->color.r != obj->prev->color.r) ||
709 (obj->cur->color.g != obj->prev->color.g) ||
710 (obj->cur->color.b != obj->prev->color.b) ||
711 (obj->cur->color.a != obj->prev->color.a))
712 {
713 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
714 goto done;
715 }
716 /* if it changed geometry - and obviously not visibility or color */
717 /* calculate differences since we have a constant color fill */
718 /* we really only need to update the differences */
719 if ((obj->cur->geometry.x != obj->prev->geometry.x) ||
720 (obj->cur->geometry.y != obj->prev->geometry.y) ||
721 (obj->cur->geometry.w != obj->prev->geometry.w) ||
722 (obj->cur->geometry.h != obj->prev->geometry.h))
723 {
724 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
725 goto done;
726 }
727 if (obj->cur->render_op != obj->prev->render_op)
728 {
729 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
730 goto done;
731 }
732 if (!EINA_DBL_EQ(obj->cur->scale, obj->prev->scale))
733 {
734 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
735 goto done;
736 }
737
738 if (o->changed)
739 {
740 if (o->core_change)
741 {
742 if ((o->cur.h != o->prev.h) ||
743 (o->cur.w != o->prev.w) ||
744 (o->cur.font_size != o->prev.font_size) ||
745 ((o->cur.font_name) && (o->prev.font_name) &&
746 (strcmp(o->cur.font_name, o->prev.font_name))) ||
747 ((o->cur.font_name) && (!o->prev.font_name)) ||
748 ((!o->cur.font_name) && (o->prev.font_name)))
749 {
750 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
751 eo_obj, obj);
752 goto done;
753 }
754 }
755 if (o->pal_change)
756 {
757 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
758 goto done;
759 }
760 if (o->row_change)
761 {
762 int i;
763
764 for (i = 0; i < o->cur.h; i++)
765 {
766 Evas_Object_Textgrid_Row *r = &(o->cur.rows[i]);
767 if (r->ch1 >= 0)
768 {
769 Evas_Coord chx, chy, chw, chh;
770
771 chx = r->ch1 * o->cur.char_width;
772 chy = i * o->cur.char_height;
773 chw = (r->ch2 - r->ch1 + 1) * o->cur.char_width;
774 chh = o->cur.char_height;
775
776 chx -= o->cur.char_width;
777 chy -= o->cur.char_height;
778 chw += o->cur.char_width * 2;
779 chh += o->cur.char_height * 2;
780
781 chx += obj->cur->geometry.x;
782 chy += obj->cur->geometry.y;
783 RECTS_CLIP_TO_RECT(chx, chy, chw, chh,
784 obj->cur->cache.clip.x,
785 obj->cur->cache.clip.y,
786 obj->cur->cache.clip.w,
787 obj->cur->cache.clip.h);
788 evas_add_rect(&obj->layer->evas->clip_changes,
789 chx, chy, chw, chh);
790 }
791 }
792 }
793 }
794
795 done:
796 o->core_change = 0;
797 o->row_change = 0;
798 o->pal_change = 0;
799 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, eo_obj, is_v, was_v);
800 }
801
802 static void
evas_object_textgrid_render_post(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,void * type_private_data)803 evas_object_textgrid_render_post(Evas_Object *eo_obj EINA_UNUSED,
804 Evas_Object_Protected_Data *obj,
805 void *type_private_data)
806 {
807 /* this moves the current data to the previous state parts of the object */
808 /* in whatever way is safest for the object. also if we don't need object */
809 /* data anymore we can free it if the object deems this is a good idea */
810 Evas_Textgrid_Data *o = type_private_data;
811 /* remove those pesky changes */
812 evas_object_clip_changes_clean(obj);
813 /* move cur to prev safely for object data */
814 evas_object_cur_prev(obj);
815 o->prev = o->cur;
816 }
817
818 static void *
evas_object_textgrid_engine_data_get(Evas_Object * eo_obj)819 evas_object_textgrid_engine_data_get(Evas_Object *eo_obj)
820 {
821 Evas_Textgrid_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
822 if (!o) return NULL;
823 return o->font_normal; /* TODO: why ? */
824 }
825
826 static int
evas_object_textgrid_is_opaque(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj EINA_UNUSED,void * type_private_data EINA_UNUSED)827 evas_object_textgrid_is_opaque(Evas_Object *eo_obj EINA_UNUSED,
828 Evas_Object_Protected_Data *obj EINA_UNUSED,
829 void *type_private_data EINA_UNUSED)
830 {
831 /* this returns 1 if the internal object data implies that the object is
832 currently fully opaque over the entire gradient it occupies */
833 return 0;
834 }
835
836 static int
evas_object_textgrid_was_opaque(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj EINA_UNUSED,void * type_private_data EINA_UNUSED)837 evas_object_textgrid_was_opaque(Evas_Object *eo_obj EINA_UNUSED,
838 Evas_Object_Protected_Data *obj EINA_UNUSED,
839 void *type_private_data EINA_UNUSED)
840 {
841 /* this returns 1 if the internal object data implies that the object was
842 currently fully opaque over the entire gradient it occupies */
843 return 0;
844 }
845
846 EOLIAN static void
_evas_textgrid_efl_gfx_entity_scale_set(Evas_Object * eo_obj,Evas_Textgrid_Data * o,double scale)847 _evas_textgrid_efl_gfx_entity_scale_set(Evas_Object *eo_obj, Evas_Textgrid_Data *o,
848 double scale)
849 {
850 int font_size;
851 const char *font_name;
852
853 if (EINA_DBL_EQ(efl_gfx_entity_scale_get(eo_obj), scale)) return;
854 efl_gfx_entity_scale_set(efl_super(eo_obj, MY_CLASS), scale);
855
856 font_name = eina_stringshare_add(o->cur.font_name);
857 font_size = o->cur.font_size;
858 if (o->cur.font_name) eina_stringshare_del(o->cur.font_name);
859 o->cur.font_name = NULL;
860 o->prev.font_name = NULL;
861 o->cur.font_size = 0;
862 o->prev.font_size = 0;
863 evas_object_textgrid_font_set(eo_obj, font_name, font_size);
864 eina_stringshare_del(font_name);
865 }
866
867 /********************* LOCAL *********************/
868
869 /********************* API *********************/
870
871 EAPI Evas_Object *
evas_object_textgrid_add(Evas * e)872 evas_object_textgrid_add(Evas *e)
873 {
874 e = evas_find(e);
875 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(e, EVAS_CANVAS_CLASS), NULL);
876 return efl_add(EVAS_TEXTGRID_CLASS, e, efl_canvas_object_legacy_ctor(efl_added));
877 }
878
879 EOLIAN static Eo *
_evas_textgrid_efl_object_constructor(Eo * eo_obj,Evas_Textgrid_Data * class_data EINA_UNUSED)880 _evas_textgrid_efl_object_constructor(Eo *eo_obj, Evas_Textgrid_Data *class_data EINA_UNUSED)
881 {
882 eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
883
884 evas_object_textgrid_init(eo_obj);
885
886 return eo_obj;
887 }
888
889 EOLIAN static void
_evas_textgrid_grid_size_set(Eo * eo_obj,Evas_Textgrid_Data * o,int w,int h)890 _evas_textgrid_grid_size_set(Eo *eo_obj, Evas_Textgrid_Data *o, int w, int h)
891 {
892 int i;
893 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
894
895 if ((h <= 0) || (w <= 0)) return;
896
897 if ((o->cur.w == w) && (o->cur.h == h)) return;
898
899 evas_object_async_block(obj);
900 evas_object_textgrid_rows_clear(eo_obj);
901 if (o->cur.rows)
902 {
903 free(o->cur.rows);
904 o->cur.rows = NULL;
905 }
906 if (o->cur.cells)
907 {
908 free(o->cur.cells);
909 o->cur.cells = NULL;
910 }
911 o->cur.cells = calloc(w * h, sizeof(Evas_Textgrid_Cell));
912 if (!o->cur.cells) return;
913 o->cur.rows = calloc(h, sizeof(Evas_Object_Textgrid_Row));
914 if (!o->cur.rows)
915 {
916 free(o->cur.cells);
917 o->cur.cells = NULL;
918 return;
919 }
920 for (i = 0; i < h; i++)
921 {
922 o->cur.rows[i].ch1 = 0;
923 o->cur.rows[i].ch2 = w - 1;
924 }
925 o->cur.w = w;
926 o->cur.h = h;
927 o->changed = 1;
928 o->core_change = 1;
929 evas_object_change(eo_obj, obj);
930 }
931
932 EOLIAN static void
_evas_textgrid_grid_size_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o,int * w,int * h)933 _evas_textgrid_grid_size_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o, int *w, int *h)
934 {
935 if (w) *w = o->cur.w;
936 if (h) *h = o->cur.h;
937 }
938
939 EOLIAN static void
_evas_textgrid_efl_text_font_font_source_set(Eo * eo_obj,Evas_Textgrid_Data * o,const char * font_source)940 _evas_textgrid_efl_text_font_font_source_set(Eo *eo_obj, Evas_Textgrid_Data *o, const char *font_source)
941 {
942 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
943
944 if ((!font_source) || (!*font_source))
945 return;
946
947 if ((o->cur.font_source) && (font_source) &&
948 (!strcmp(o->cur.font_source, font_source))) return;
949
950 evas_object_async_block(obj);
951 eina_stringshare_replace(&o->cur.font_source, font_source);
952 o->changed = 1;
953 o->core_change = 1;
954 evas_object_change(eo_obj, obj);
955 }
956
957 EOLIAN static const char*
_evas_textgrid_efl_text_font_font_source_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o)958 _evas_textgrid_efl_text_font_font_source_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o)
959 {
960 return o->cur.font_source;
961 }
962
963 static int
_alternate_font_weight_slant(Evas_Object_Protected_Data * obj,Evas_Textgrid_Data * o,Evas_Font_Set ** fontp,Evas_Font_Description * fdesc,const char * kind)964 _alternate_font_weight_slant(Evas_Object_Protected_Data *obj,
965 Evas_Textgrid_Data *o,
966 Evas_Font_Set **fontp,
967 Evas_Font_Description *fdesc,
968 const char *kind)
969 {
970 int ret = -1;
971 Evas_Font_Set *font;
972
973 font = evas_font_load(obj->layer->evas->font_path,
974 obj->layer->evas->hinting,
975 fdesc,
976 o->cur.font_source,
977 (int)(((double) o->cur.font_size) *
978 obj->cur->scale),
979 o->cur.bitmap_scalable);
980 if (font)
981 {
982 Eina_Unicode W[2] = { 'O', 0 };
983 Evas_Font_Instance *script_fi = NULL;
984 Evas_Font_Instance *cur_fi = NULL;
985 Evas_Text_Props text_props;
986 Evas_Script_Type script;
987 int advance, vadvance, ascent;
988
989 script = evas_common_language_script_type_get(W, 1);
990 ENFN->font_run_end_get(ENC, font, &script_fi, &cur_fi,
991 script, W, 1);
992 memset(&text_props, 0, sizeof(Evas_Text_Props));
993 evas_common_text_props_script_set(&text_props, script);
994 ENFN->font_text_props_info_create(ENC, cur_fi, W, &text_props,
995 NULL, 0, 1,
996 EVAS_TEXT_PROPS_MODE_NONE,
997 fdesc->lang);
998 advance = ENFN->font_h_advance_get(ENC, font, &text_props);
999 vadvance = ENFN->font_v_advance_get(ENC, font, &text_props);
1000 ascent = ENFN->font_ascent_get(ENC, font);
1001 DBG("on font '%s', with alternate weight/slant %s, "
1002 "width: %d vs %d, height: %d vs %d, ascent: %d vs %d",
1003 fdesc->name, kind,
1004 o->cur.char_width, advance,
1005 o->cur.char_height, vadvance,
1006 o->ascent, ascent);
1007 if ((o->cur.char_width != advance) ||
1008 (o->cur.char_height != vadvance) ||
1009 (o->ascent != ascent))
1010 {
1011 evas_font_free(font);
1012 }
1013 else
1014 {
1015 *fontp = font;
1016 ret = 0;
1017 }
1018 evas_common_text_props_content_unref(&text_props);
1019 }
1020 else
1021 {
1022 DBG("cannot load font '%s' with alternate weight/slant %s",
1023 fdesc->name, kind);
1024 }
1025 return ret;
1026 }
1027
1028 static void
_evas_textgrid_font_reload(Eo * eo_obj,Evas_Textgrid_Data * o)1029 _evas_textgrid_font_reload(Eo *eo_obj, Evas_Textgrid_Data *o)
1030 {
1031 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1032 Eina_Bool pass = EINA_FALSE, freeze = EINA_FALSE;
1033 Eina_Bool source_invisible = EINA_FALSE;
1034 Evas_Font_Description *fdesc;
1035 Eina_List *was = NULL;
1036
1037 fdesc = o->cur.font_description_normal;
1038
1039 if (!(obj->layer->evas->is_frozen))
1040 {
1041 pass = evas_event_passes_through(eo_obj, obj);
1042 freeze = evas_event_freezes_through(eo_obj, obj);
1043 source_invisible = evas_object_is_source_invisible(eo_obj, obj);
1044 if ((!pass) && (!freeze) && (!source_invisible))
1045 was = _evas_pointer_list_in_rect_get(obj->layer->evas, eo_obj, obj,
1046 1, 1);
1047 }
1048
1049 if (o->font_normal)
1050 {
1051 evas_font_free(o->font_normal);
1052 o->font_normal = NULL;
1053 }
1054
1055 o->font_normal = evas_font_load(obj->layer->evas->font_path,
1056 obj->layer->evas->hinting,
1057 o->cur.font_description_normal,
1058 o->cur.font_source,
1059 (int)(((double) o->cur.font_size) *
1060 obj->cur->scale),
1061 o->cur.bitmap_scalable);
1062 if (o->font_normal)
1063 {
1064 Eina_Unicode W[2] = { 'O', 0 };
1065 Evas_Font_Instance *script_fi = NULL;
1066 Evas_Font_Instance *cur_fi = NULL;
1067 Evas_Text_Props text_props;
1068 Evas_Script_Type script;
1069 int advance, vadvance;
1070
1071 script = evas_common_language_script_type_get(W, 1);
1072 ENFN->font_run_end_get(ENC, o->font_normal, &script_fi, &cur_fi,
1073 script, W, 1);
1074 memset(&text_props, 0, sizeof(Evas_Text_Props));
1075 evas_common_text_props_script_set(&text_props, script);
1076 ENFN->font_text_props_info_create(ENC, cur_fi, W, &text_props,
1077 NULL, 0, 1,
1078 EVAS_TEXT_PROPS_MODE_NONE,
1079 fdesc->lang);
1080 advance = ENFN->font_h_advance_get(ENC, o->font_normal, &text_props);
1081 vadvance = ENFN->font_v_advance_get(ENC, o->font_normal, &text_props);
1082 o->cur.char_width = advance;
1083 o->cur.char_height = vadvance;
1084 o->ascent = ENFN->font_ascent_get(ENC, o->font_normal);
1085 evas_common_text_props_content_unref(&text_props);
1086 }
1087 else
1088 {
1089 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
1090 {
1091 state_write->geometry.w = 0;
1092 state_write->geometry.h = 0;
1093 }
1094 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
1095
1096 o->ascent = 0;
1097 }
1098
1099 DBG("font: '%s' weight: %d, slant: %d",
1100 fdesc->name, fdesc->weight, fdesc->slant);
1101
1102 /* Bold */
1103 if (o->font_bold)
1104 {
1105 evas_font_free(o->font_bold);
1106 o->font_bold = NULL;
1107 }
1108 if ((fdesc->weight == EVAS_FONT_WEIGHT_NORMAL) ||
1109 (fdesc->weight == EVAS_FONT_WEIGHT_BOOK))
1110 {
1111 Evas_Font_Description *bold_desc = evas_font_desc_dup(fdesc);
1112
1113 eina_stringshare_del(bold_desc->style);
1114 bold_desc->style = NULL;
1115
1116 bold_desc->weight = EVAS_FONT_WEIGHT_BOLD;
1117 _alternate_font_weight_slant(obj, o, &o->font_bold, bold_desc,
1118 "bold");
1119 evas_font_desc_unref(bold_desc);
1120 }
1121
1122 /* Italic */
1123 if (o->font_italic)
1124 {
1125 evas_font_free(o->font_italic);
1126 o->font_italic = NULL;
1127 }
1128 if (fdesc->slant == EVAS_FONT_SLANT_NORMAL)
1129 {
1130 Evas_Font_Description *italic_desc = evas_font_desc_dup(fdesc);
1131 int ret;
1132
1133 eina_stringshare_del(italic_desc->style);
1134 italic_desc->style = NULL;
1135
1136 italic_desc->slant = EVAS_FONT_SLANT_ITALIC;
1137 ret = _alternate_font_weight_slant(obj, o, &o->font_italic,
1138 italic_desc, "italic");
1139 if (ret != 0)
1140 {
1141 italic_desc->slant = EVAS_FONT_SLANT_OBLIQUE;
1142 _alternate_font_weight_slant(obj, o, &o->font_italic,
1143 italic_desc,
1144 "oblique");
1145 }
1146 evas_font_desc_unref(italic_desc);
1147 }
1148
1149 /* BoldItalic */
1150 if (o->font_bolditalic)
1151 {
1152 evas_font_free(o->font_bolditalic);
1153 o->font_bolditalic = NULL;
1154 }
1155 if (fdesc->slant == EVAS_FONT_SLANT_NORMAL &&
1156 ((fdesc->weight == EVAS_FONT_WEIGHT_NORMAL) ||
1157 (fdesc->weight == EVAS_FONT_WEIGHT_BOOK)))
1158 {
1159 Evas_Font_Description *bolditalic_desc = evas_font_desc_dup(fdesc);
1160 int ret;
1161
1162 eina_stringshare_del(bolditalic_desc->style);
1163 bolditalic_desc->style = NULL;
1164
1165 bolditalic_desc->slant = EVAS_FONT_SLANT_ITALIC;
1166 bolditalic_desc->weight = EVAS_FONT_WEIGHT_BOLD;
1167 ret = _alternate_font_weight_slant(obj, o, &o->font_bolditalic,
1168 bolditalic_desc,
1169 "bolditalic");
1170 if (ret != 0)
1171 {
1172 bolditalic_desc->slant = EVAS_FONT_SLANT_OBLIQUE;
1173 _alternate_font_weight_slant(obj, o, &o->font_bolditalic,
1174 bolditalic_desc,
1175 "boldoblique");
1176 }
1177 evas_font_desc_unref(bolditalic_desc);
1178 }
1179
1180 o->changed = 1;
1181 evas_object_change(eo_obj, obj);
1182 evas_object_clip_dirty(eo_obj, obj);
1183 evas_object_coords_recalc(eo_obj, obj);
1184 if (!obj->layer->evas->is_frozen && !pass && !freeze && obj->cur->visible)
1185 _evas_canvas_event_pointer_in_list_mouse_move_feed(obj->layer->evas, was, eo_obj, obj, 1, 1, EINA_TRUE, NULL);
1186 eina_list_free(was);
1187 evas_object_inform_call_resize(eo_obj, obj);
1188 o->changed = 1;
1189 o->core_change = 1;
1190 evas_object_textgrid_rows_clear(eo_obj);
1191 evas_object_change(eo_obj, obj);
1192 }
1193
1194 EOLIAN static void
_evas_textgrid_efl_text_font_font_family_set(Eo * eo_obj,Evas_Textgrid_Data * o,const char * font_name)1195 _evas_textgrid_efl_text_font_font_family_set(Eo *eo_obj,
1196 Evas_Textgrid_Data *o,
1197 const char *font_name)
1198 {
1199 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1200 Evas_Font_Description *fdesc;
1201
1202 EINA_SAFETY_ON_TRUE_RETURN((!font_name) || (!*font_name));
1203
1204 evas_object_async_block(obj);
1205 fdesc = evas_font_desc_new();
1206 /* Set default language according to locale. */
1207 eina_stringshare_replace(&(fdesc->lang),
1208 evas_font_lang_normalize("auto"));
1209 evas_font_name_parse(fdesc, font_name);
1210 if (o->cur.font_description_normal &&
1211 !evas_font_desc_cmp(fdesc, o->cur.font_description_normal))
1212 {
1213 evas_font_desc_unref(fdesc);
1214 return;
1215 }
1216
1217 if (o->cur.font_description_normal)
1218 evas_font_desc_unref(o->cur.font_description_normal);
1219 o->cur.font_description_normal = fdesc;
1220
1221 eina_stringshare_replace(&o->cur.font_name, font_name);
1222 o->prev.font_name = NULL;
1223
1224 _evas_textgrid_font_reload(eo_obj, o);
1225 }
1226
1227 EOLIAN static const char *
_evas_textgrid_efl_text_font_font_family_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o)1228 _evas_textgrid_efl_text_font_font_family_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o)
1229 {
1230 return o->cur.font_name;
1231 }
1232
1233 EOLIAN static void
_evas_textgrid_efl_text_font_font_size_set(Eo * eo_obj,Evas_Textgrid_Data * o,Evas_Font_Size font_size)1234 _evas_textgrid_efl_text_font_font_size_set(Eo *eo_obj,
1235 Evas_Textgrid_Data *o,
1236 Evas_Font_Size font_size)
1237 {
1238 EINA_SAFETY_ON_TRUE_RETURN(font_size <= 0);
1239
1240 if (font_size == o->cur.font_size) return;
1241
1242 o->cur.font_size = font_size;
1243
1244 _evas_textgrid_font_reload(eo_obj, o);
1245 }
1246
1247 EOLIAN static Evas_Font_Size
_evas_textgrid_efl_text_font_font_size_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o)1248 _evas_textgrid_efl_text_font_font_size_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o)
1249 {
1250 return o->cur.font_size;
1251 }
1252
1253 EOLIAN static void
_evas_textgrid_cell_size_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o,int * w,int * h)1254 _evas_textgrid_cell_size_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o, int *w, int *h)
1255 {
1256 if (w) *w = o->cur.char_width;
1257 if (h) *h = o->cur.char_height;
1258 }
1259
1260 EOLIAN static void
_evas_textgrid_palette_set(Eo * eo_obj,Evas_Textgrid_Data * o,Evas_Textgrid_Palette pal,int idx,int r,int g,int b,int a)1261 _evas_textgrid_palette_set(Eo *eo_obj, Evas_Textgrid_Data *o, Evas_Textgrid_Palette pal, int idx, int r, int g, int b, int a)
1262 {
1263
1264 Eina_Array *palette;
1265 Evas_Object_Textgrid_Color *color, *c;
1266 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1267 int count, i;
1268
1269 if ((idx < 0) || (idx > 255)) return;
1270
1271 if (a > 255) a = 255;
1272 if (a < 0) a = 0;
1273 if (r > 255) r = 255;
1274 if (r < 0) r = 0;
1275 if (g > 255) g = 255;
1276 if (g < 0) g = 0;
1277 if (b > 255) b = 255;
1278 if (b < 0) b = 0;
1279 if (r > a)
1280 {
1281 r = a;
1282 ERR("Evas only handles pre multiplied colors!");
1283 }
1284 if (g > a)
1285 {
1286 g = a;
1287 ERR("Evas only handles pre multiplied colors!");
1288 }
1289 if (b > a)
1290 {
1291 b = a;
1292 ERR("Evas only handles pre multiplied colors!");
1293 }
1294
1295 evas_object_async_block(obj);
1296 switch (pal)
1297 {
1298 case EVAS_TEXTGRID_PALETTE_STANDARD:
1299 palette = &(o->cur.palette_standard);
1300 break;
1301 case EVAS_TEXTGRID_PALETTE_EXTENDED:
1302 palette = &(o->cur.palette_extended);
1303 break;
1304 default:
1305 return;
1306 }
1307
1308 count = eina_array_count(palette);
1309 if (idx < count)
1310 {
1311 color = eina_array_data_get(palette, idx);
1312 if (color->a == a &&
1313 color->r == r &&
1314 color->g == g &&
1315 color->b == b)
1316 return;
1317 }
1318 else
1319 {
1320 color = malloc(sizeof(Evas_Object_Textgrid_Color));
1321 if (!color) return;
1322 }
1323
1324 color->a = a;
1325 color->r = r;
1326 color->g = g;
1327 color->b = b;
1328
1329 if (idx < count) eina_array_data_set(palette, idx, color);
1330 else if (idx == count) eina_array_push(palette, color);
1331 else
1332 {
1333 for (i = count; i < idx; i++)
1334 {
1335 c = calloc(1, sizeof(Evas_Object_Textgrid_Color));
1336 if (!c)
1337 {
1338 ERR("Evas cannot allocate memory");
1339 free(color);
1340 return;
1341 }
1342 eina_array_push(palette, c);
1343 }
1344 eina_array_push(palette, color);
1345 }
1346 o->changed = 1;
1347 o->pal_change = 1;
1348 evas_object_textgrid_rows_clear(eo_obj);
1349 evas_object_change(eo_obj, obj);
1350 }
1351
1352 EOLIAN static void
_evas_textgrid_palette_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o,Evas_Textgrid_Palette pal,int idx,int * r,int * g,int * b,int * a)1353 _evas_textgrid_palette_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o, Evas_Textgrid_Palette pal, int idx, int *r, int *g, int *b, int *a)
1354 {
1355 Eina_Array *palette;
1356 Evas_Object_Textgrid_Color *color;
1357
1358 if (idx < 0) return;
1359
1360 switch (pal)
1361 {
1362 case EVAS_TEXTGRID_PALETTE_STANDARD:
1363 palette = &(((Evas_Textgrid_Data *)o)->cur.palette_standard);
1364 break;
1365 case EVAS_TEXTGRID_PALETTE_EXTENDED:
1366 palette = &(((Evas_Textgrid_Data *)o)->cur.palette_extended);
1367 break;
1368 default:
1369 return;
1370 }
1371
1372 if (idx >= (int)eina_array_count(palette)) return;
1373 color = eina_array_data_get(palette, idx);
1374 if (!color) return;
1375
1376 if (a) *a = color->a;
1377 if (r) *r = color->r;
1378 if (g) *g = color->g;
1379 if (b) *b = color->b;
1380 }
1381
1382 EOLIAN static void
_evas_textgrid_supported_font_styles_set(Eo * eo_obj,Evas_Textgrid_Data * o,Evas_Textgrid_Font_Style styles)1383 _evas_textgrid_supported_font_styles_set(Eo *eo_obj, Evas_Textgrid_Data *o, Evas_Textgrid_Font_Style styles)
1384 {
1385 /* FIXME: to do */
1386 if (styles)
1387 {
1388 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1389 o->changed = 1;
1390 evas_object_change(eo_obj, obj);
1391 }
1392 }
1393
1394 EOLIAN static Evas_Textgrid_Font_Style
_evas_textgrid_supported_font_styles_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o EINA_UNUSED)1395 _evas_textgrid_supported_font_styles_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o EINA_UNUSED)
1396 {
1397 /* FIXME: to do */
1398 return EVAS_TEXTGRID_FONT_STYLE_NORMAL;
1399 }
1400
1401 EOLIAN static void
_evas_textgrid_cellrow_set(Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o,int y,const Evas_Textgrid_Cell * row)1402 _evas_textgrid_cellrow_set(Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o, int y, const Evas_Textgrid_Cell *row)
1403 {
1404 if (!row) return;
1405
1406 if ((y < 0) || (y >= o->cur.h)) return;
1407 }
1408
1409 EOLIAN static Evas_Textgrid_Cell*
_evas_textgrid_cellrow_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o,int y)1410 _evas_textgrid_cellrow_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o, int y)
1411 {
1412 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1413 evas_object_async_block(obj);
1414 if ((y < 0) || (y >= o->cur.h)) return NULL;
1415
1416 return o->cur.cells + (y * o->cur.w);
1417 }
1418
1419 EOLIAN static void
_evas_textgrid_update_add(Eo * eo_obj,Evas_Textgrid_Data * o,int x,int y,int w,int h)1420 _evas_textgrid_update_add(Eo *eo_obj, Evas_Textgrid_Data *o, int x, int y, int w, int h)
1421 {
1422 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1423 int i, x2;
1424
1425 RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, o->cur.w, o->cur.h);
1426 if ((w <= 0) || (h <= 0)) return;
1427
1428 evas_object_async_block(obj);
1429 x2 = x + w - 1;
1430 for (i = 0; i < h; i++)
1431 {
1432 Evas_Object_Textgrid_Row *r = &(o->cur.rows[y + i]);
1433
1434 if (r->ch1 < 0)
1435 {
1436 evas_object_textgrid_row_clear(o, r);
1437 r->ch1 = x;
1438 r->ch2 = x2;
1439 }
1440 else
1441 {
1442 if (x < r->ch1) r->ch1 = x;
1443 if (x2 > r->ch2) r->ch2 = x2;
1444 }
1445 }
1446 o->row_change = 1;
1447 o->changed = 1;
1448 evas_object_change(eo_obj, obj);
1449 }
1450
1451 EOLIAN static void
_evas_textgrid_efl_object_dbg_info_get(Eo * eo_obj,Evas_Textgrid_Data * o EINA_UNUSED,Efl_Dbg_Info * root)1452 _evas_textgrid_efl_object_dbg_info_get(Eo *eo_obj, Evas_Textgrid_Data *o EINA_UNUSED, Efl_Dbg_Info *root)
1453 {
1454 efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root);
1455 Efl_Dbg_Info *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
1456 Efl_Dbg_Info *node;
1457
1458 const char *text;
1459 int size;
1460 text = efl_text_font_family_get(eo_obj);
1461 size = efl_text_font_size_get(eo_obj);
1462 EFL_DBG_INFO_APPEND(group, "Font", EINA_VALUE_TYPE_STRING, text);
1463 EFL_DBG_INFO_APPEND(group, "Text size", EINA_VALUE_TYPE_INT, size);
1464
1465 text = efl_text_font_source_get(eo_obj);
1466 EFL_DBG_INFO_APPEND(group, "Font source", EINA_VALUE_TYPE_STRING, text);
1467
1468 {
1469 int w, h;
1470 evas_obj_textgrid_grid_size_get(eo_obj, &w, &h);
1471 node = EFL_DBG_INFO_LIST_APPEND(group, "Grid size");
1472 EFL_DBG_INFO_APPEND(node, "w", EINA_VALUE_TYPE_INT, w);
1473 EFL_DBG_INFO_APPEND(node, "h", EINA_VALUE_TYPE_INT, h);
1474 }
1475 }
1476
1477 EAPI void
evas_object_textgrid_font_source_set(Eo * obj,const char * font_source)1478 evas_object_textgrid_font_source_set(Eo *obj, const char *font_source)
1479 {
1480 efl_text_font_source_set((Eo *) obj, font_source);
1481 }
1482
1483 EAPI const char *
evas_object_textgrid_font_source_get(const Eo * obj)1484 evas_object_textgrid_font_source_get(const Eo *obj)
1485 {
1486 const char *font_source = NULL;
1487 font_source = efl_text_font_source_get((Eo *) obj);
1488 return font_source;
1489 }
1490
1491 EAPI void
evas_object_textgrid_font_set(Eo * obj,const char * font_name,Evas_Font_Size font_size)1492 evas_object_textgrid_font_set(Eo *obj, const char *font_name, Evas_Font_Size font_size)
1493 {
1494 efl_text_font_family_set((Eo *) obj, font_name);
1495 efl_text_font_size_set((Eo *) obj, font_size);
1496 }
1497
1498 EAPI void
evas_object_textgrid_font_get(const Eo * obj,const char ** font_name,Evas_Font_Size * font_size)1499 evas_object_textgrid_font_get(const Eo *obj, const char **font_name, Evas_Font_Size *font_size)
1500 {
1501 if (font_name) *font_name = efl_text_font_family_get((Eo *) obj);
1502 if (font_size) *font_size = efl_text_font_size_get((Eo *) obj);
1503 }
1504
1505 EOLIAN static void
_evas_textgrid_efl_text_font_font_bitmap_scalable_set(Eo * eo_obj,Evas_Textgrid_Data * o,Efl_Text_Font_Bitmap_Scalable bitmap_scalable)1506 _evas_textgrid_efl_text_font_font_bitmap_scalable_set(Eo *eo_obj, Evas_Textgrid_Data *o, Efl_Text_Font_Bitmap_Scalable bitmap_scalable)
1507 {
1508 if (o->cur.bitmap_scalable == bitmap_scalable) return;
1509 o->prev.bitmap_scalable = o->cur.bitmap_scalable;
1510 o->cur.bitmap_scalable = bitmap_scalable;
1511 _evas_textgrid_font_reload(eo_obj, o);
1512 }
1513
1514 EOLIAN static Efl_Text_Font_Bitmap_Scalable
_evas_textgrid_efl_text_font_font_bitmap_scalable_get(const Eo * eo_obj EINA_UNUSED,Evas_Textgrid_Data * o)1515 _evas_textgrid_efl_text_font_font_bitmap_scalable_get(const Eo *eo_obj EINA_UNUSED, Evas_Textgrid_Data *o)
1516 {
1517 return o->cur.bitmap_scalable;
1518 }
1519
1520 #define EVAS_TEXTGRID_EXTRA_OPS \
1521 EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _evas_textgrid_efl_object_dbg_info_get)
1522
1523 #include "canvas/evas_textgrid_eo.c"
1524