1 #include "evas_common.h"
2 #include "evas_private.h"
5 #define ENFN obj->layer->evas->engine.func
6 #define ENDT obj->layer->evas->engine.data.output
8 /* private magic number for text objects */
9 static const char o_type[] = "text";
11 /* private struct for text object internal data */
12 typedef struct _Evas_Object_Text Evas_Object_Text;
14 struct _Evas_Object_Text
24 unsigned char r, g, b, a;
25 } outline, shadow, glow, glow2;
30 float ascent, descent;
31 float max_ascent, max_descent;
38 /* private methods for text objects */
39 static void evas_object_text_init(Evas_Object *obj);
40 static void *evas_object_text_new(void);
41 static void evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
42 static void evas_object_text_free(Evas_Object *obj);
43 static void evas_object_text_render_pre(Evas_Object *obj);
44 static void evas_object_text_render_post(Evas_Object *obj);
46 static int evas_object_text_is_opaque(Evas_Object *obj);
47 static int evas_object_text_was_opaque(Evas_Object *obj);
49 static const Evas_Object_Func object_func =
51 /* methods (compulsory) */
52 evas_object_text_free,
53 evas_object_text_render,
54 evas_object_text_render_pre,
55 evas_object_text_render_post,
56 /* these are optional. NULL = nothing */
61 evas_object_text_is_opaque,
62 evas_object_text_was_opaque,
68 /* the actual api call to add a rect */
69 /* it has no other api calls as all properties are standard */
72 * Creates a new text @c Evas_Object on the provided @c Evas canvas.
74 * @param e The @c Evas canvas to create the text object upon.
76 * @see evas_object_text_font_source_set
77 * @see evas_object_text_font_set
78 * @see evas_object_text_text_set
80 * @returns NULL on error, A pointer to a new @c Evas_Object on success.
83 evas_object_text_add(Evas *e)
87 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
90 obj = evas_object_new();
91 evas_object_text_init(obj);
92 evas_object_inject(obj, e);
103 evas_object_text_font_source_set(Evas_Object *obj, const char *font_source)
107 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
110 o = (Evas_Object_Text *)(obj->object_data);
111 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
115 if ((o->cur.source) && (font_source) &&
116 (!strcmp(o->cur.source, font_source)))
118 if (o->cur.source) evas_stringshare_del(o->cur.source);
119 if (font_source) o->cur.source = evas_stringshare_add(font_source);
120 else o->cur.source = NULL;
126 * FIXME: To be fixed.
130 evas_object_text_font_source_get(const Evas_Object *obj)
134 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
137 o = (Evas_Object_Text *)(obj->object_data);
138 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
141 return o->cur.source;
147 * FIXME: To be fixed.
151 evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size size)
154 int l = 0, r = 0, t = 0, b = 0;
155 int is, was = 0, pass = 0;
159 if (size <= 0) return;
160 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
163 o = (Evas_Object_Text *)(obj->object_data);
164 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
168 if ((o->cur.font) && (font) && (!strcmp(o->cur.font, font)))
171 if (size == o->cur.size) return;
173 if (obj->layer->evas->events_frozen <= 0)
175 pass = evas_event_passes_through(obj);
177 was = evas_object_is_in_output_rect(obj,
178 obj->layer->evas->pointer.x,
179 obj->layer->evas->pointer.y, 1, 1);
184 evas_font_free(obj->layer->evas, o->engine_data);
185 o->engine_data = NULL;
187 o->engine_data = evas_font_load(obj->layer->evas, font, o->cur.source, size);
190 if (o->cur.font) evas_stringshare_del(o->cur.font);
191 if (font) o->cur.font = evas_stringshare_add(font);
192 else o->cur.font = NULL;
196 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
197 if ((o->engine_data) && (o->cur.text))
201 ENFN->font_string_size_get(ENDT,
205 o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data);
206 o->descent = ENFN->font_descent_get(ENDT, o->engine_data);
207 o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data);
208 o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data);
209 obj->cur.geometry.w = w + l + r;
210 obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b;
211 //// obj->cur.cache.geometry.validity = 0;
217 o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data);
218 o->descent = ENFN->font_descent_get(ENDT, o->engine_data);
219 o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data);
220 o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data);
229 obj->cur.geometry.w = 0;
230 obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b;
231 //// obj->cur.cache.geometry.validity = 0;
234 evas_object_change(obj);
235 evas_object_coords_recalc(obj);
236 if (obj->layer->evas->events_frozen <= 0)
240 is = evas_object_is_in_output_rect(obj,
241 obj->layer->evas->pointer.x,
242 obj->layer->evas->pointer.y, 1, 1);
243 if ((is ^ was) && obj->cur.visible)
244 evas_event_feed_mouse_move(obj->layer->evas,
245 obj->layer->evas->pointer.x,
246 obj->layer->evas->pointer.y,
247 obj->layer->evas->last_timestamp,
251 evas_object_inform_call_resize(obj);
255 * Query evas for font information of a text @c Evas_Object.
257 * This function allows the font name and size of a text @c Evas_Object as
258 * created with evas_object_text_add() to be queried. Be aware that the font
259 * name string is still owned by Evas and should NOT have free() called on
260 * it by the caller of the function.
262 * @param obj The evas text object to query for font information.
263 * @param font A pointer to the location to store the font name in (may be NULL).
264 * @param size A pointer to the location to store the font size in (may be NULL).
267 evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_Size *size)
271 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
272 if (font) *font = "";
276 o = (Evas_Object_Text *)(obj->object_data);
277 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
278 if (font) *font = "";
282 if (font) *font = o->cur.font;
283 if (size) *size = o->cur.size;
287 * Sets the text to be displayed by the given evas text object.
288 * @param obj Evas text object.
289 * @param text Text to display.
292 evas_object_text_text_set(Evas_Object *obj, const char *text)
297 if (!text) text = "";
298 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
301 o = (Evas_Object_Text *)(obj->object_data);
302 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
305 if ((o->cur.text) && (text) && (!strcmp(o->cur.text, text))) return;
306 was = evas_object_is_in_output_rect(obj,
307 obj->layer->evas->pointer.x,
308 obj->layer->evas->pointer.y, 1, 1);
310 if (o->cur.text) evas_stringshare_del(o->cur.text);
311 if ((text) && (*text)) o->cur.text = evas_stringshare_add(text);
312 else o->cur.text = NULL;
314 if ((o->engine_data) && (o->cur.text))
317 int l = 0, r = 0, t = 0, b = 0;
319 ENFN->font_string_size_get(ENDT,
323 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
324 obj->cur.geometry.w = w + l + r;
325 obj->cur.geometry.h = h + t + b;
326 //// obj->cur.cache.geometry.validity = 0;
332 evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b);
333 obj->cur.geometry.w = 0;
334 obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b;
335 //// obj->cur.cache.geometry.validity = 0;
338 evas_object_change(obj);
339 evas_object_coords_recalc(obj);
340 is = evas_object_is_in_output_rect(obj,
341 obj->layer->evas->pointer.x,
342 obj->layer->evas->pointer.y, 1, 1);
343 if ((is || was) && obj->cur.visible)
344 evas_event_feed_mouse_move(obj->layer->evas,
345 obj->layer->evas->pointer.x,
346 obj->layer->evas->pointer.y,
347 obj->layer->evas->last_timestamp,
349 evas_object_inform_call_resize(obj);
353 * Retrieves the text currently being displayed by the given evas text object.
354 * @param obj The given evas text object.
355 * @return The text currently being displayed. Do not free it.
358 evas_object_text_text_get(const Evas_Object *obj)
362 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
365 o = (Evas_Object_Text *)(obj->object_data);
366 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
375 * FIXME: To be fixed.
379 evas_object_text_ascent_get(const Evas_Object *obj)
383 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
386 o = (Evas_Object_Text *)(obj->object_data);
387 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
396 * FIXME: To be fixed.
400 evas_object_text_descent_get(const Evas_Object *obj)
404 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
407 o = (Evas_Object_Text *)(obj->object_data);
408 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
417 * FIXME: To be fixed.
421 evas_object_text_max_ascent_get(const Evas_Object *obj)
425 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
428 o = (Evas_Object_Text *)(obj->object_data);
429 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
432 return o->max_ascent;
438 * FIXME: To be fixed.
442 evas_object_text_max_descent_get(const Evas_Object *obj)
446 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
449 o = (Evas_Object_Text *)(obj->object_data);
450 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
453 return o->max_descent;
459 * FIXME: To be fixed.
463 evas_object_text_inset_get(const Evas_Object *obj)
467 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
470 o = (Evas_Object_Text *)(obj->object_data);
471 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
474 if (!o->engine_data) return 0;
475 if (!o->cur.text) return 0;
476 return ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
482 * FIXME: To be fixed.
486 evas_object_text_horiz_advance_get(const Evas_Object *obj)
490 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
493 o = (Evas_Object_Text *)(obj->object_data);
494 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
497 if (!o->engine_data) return 0;
498 if (!o->cur.text) return 0;
499 return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text);
505 * FIXME: To be fixed.
509 evas_object_text_vert_advance_get(const Evas_Object *obj)
513 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
516 o = (Evas_Object_Text *)(obj->object_data);
517 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
520 if (!o->engine_data) return 0;
521 if (!o->cur.text) return o->ascent + o->descent;
522 return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text);
526 * Retrieve position and dimension information of a character within a text @c Evas_Object.
528 * This function is used to obtain the X, Y, width and height of a the character
529 * located at @p pos within the @c Evas_Object @p obj. @p obj must be a text object
530 * as created with evas_object_text_add(). Any of the @c Evas_Coord parameters (@p cx,
531 * @p cy, @p cw, @p ch) may be NULL in which case no value will be assigned to that
534 * @param obj The text object to retrieve position information for.
535 * @param pos The character position to request co-ordinates for.
536 * @param cx A pointer to an @c Evas_Coord to store the X value in (can be NULL).
537 * @param cy A pointer to an @c Evas_Coord to store the Y value in (can be NULL).
538 * @param cw A pointer to an @c Evas_Coord to store the Width value in (can be NULL).
539 * @param ch A pointer to an @c Evas_Coord to store the Height value in (can be NULL).
541 * @returns 0 on error, 1 on success.
544 evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
547 int l = 0, r = 0, t = 0, b = 0;
548 int ret, x = 0, y = 0, w = 0, h = 0;
551 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
554 o = (Evas_Object_Text *)(obj->object_data);
555 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
558 if (!o->engine_data) return 0;
559 if (!o->cur.text) return 0;
561 ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
562 ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text,
566 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
567 y += o->max_ascent - t;
574 if (x + w > obj->cur.geometry.w) w = obj->cur.geometry.w - x;
581 if (y + h > obj->cur.geometry.h) h = obj->cur.geometry.h - y;
585 if (cw) *cw = w + l + r;
586 if (ch) *ch = h + t + b;
593 * FIXME: To be fixed.
597 evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
600 int l = 0, r = 0, t = 0, b = 0;
601 int ret, rx = 0, ry = 0, rw = 0, rh = 0;
604 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
607 o = (Evas_Object_Text *)(obj->object_data);
608 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
611 if (!o->engine_data) return -1;
612 if (!o->cur.text) return -1;
614 ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
615 ret = ENFN->font_char_at_coords_get(ENDT,
622 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
623 ry += o->max_ascent - t;
630 if (rx + rw > obj->cur.geometry.w) rw = obj->cur.geometry.w - rx;
637 if (ry + rh > obj->cur.geometry.h) rh = obj->cur.geometry.h - ry;
641 if (cw) *cw = rw + l + r;
642 if (ch) *ch = rh + t + b;
649 * FIXME: To be fixed.
653 evas_object_text_style_set(Evas_Object *obj, Evas_Text_Style_Type style)
656 int pl = 0, pr = 0, pt = 0, pb = 0, l = 0, r = 0, t = 0, b = 0;
658 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
661 o = (Evas_Object_Text *)(obj->object_data);
662 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
665 if (o->cur.style == style)
667 evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb);
668 o->cur.style = style;
669 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
671 obj->cur.geometry.w += (l - pl) + (r - pr);
673 obj->cur.geometry.w = 0;
674 obj->cur.geometry.h += (t - pt) + (b - pb);
675 evas_object_change(obj);
681 * FIXME: To be fixed.
684 EAPI Evas_Text_Style_Type
685 evas_object_text_style_get(const Evas_Object *obj)
689 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
690 return EVAS_TEXT_STYLE_PLAIN;
692 o = (Evas_Object_Text *)(obj->object_data);
693 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
694 return EVAS_TEXT_STYLE_PLAIN;
702 * FIXME: To be fixed.
706 evas_object_text_shadow_color_set(Evas_Object *obj, int r, int g, int b, int a)
710 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
713 o = (Evas_Object_Text *)(obj->object_data);
714 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
717 if ((o->cur.shadow.r == r) && (o->cur.shadow.g == g) &&
718 (o->cur.shadow.b == b) && (o->cur.shadow.a == a))
724 evas_object_change(obj);
730 * FIXME: To be fixed.
734 evas_object_text_shadow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
738 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
741 o = (Evas_Object_Text *)(obj->object_data);
742 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
745 if (r) *r = o->cur.shadow.r;
746 if (g) *g = o->cur.shadow.g;
747 if (b) *b = o->cur.shadow.b;
748 if (a) *a = o->cur.shadow.a;
754 * FIXME: To be fixed.
758 evas_object_text_glow_color_set(Evas_Object *obj, int r, int g, int b, int a)
762 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
765 o = (Evas_Object_Text *)(obj->object_data);
766 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
769 if ((o->cur.glow.r == r) && (o->cur.glow.g == g) &&
770 (o->cur.glow.b == b) && (o->cur.glow.a == a))
776 evas_object_change(obj);
782 * FIXME: To be fixed.
786 evas_object_text_glow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
790 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
793 o = (Evas_Object_Text *)(obj->object_data);
794 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
797 if (r) *r = o->cur.glow.r;
798 if (g) *g = o->cur.glow.g;
799 if (b) *b = o->cur.glow.b;
800 if (a) *a = o->cur.glow.a;
806 * FIXME: To be fixed.
810 evas_object_text_glow2_color_set(Evas_Object *obj, int r, int g, int b, int a)
814 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
817 o = (Evas_Object_Text *)(obj->object_data);
818 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
821 if ((o->cur.glow2.r == r) && (o->cur.glow2.g == g) &&
822 (o->cur.glow2.b == b) && (o->cur.glow2.a == a))
828 evas_object_change(obj);
834 * FIXME: To be fixed.
838 evas_object_text_glow2_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
842 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
845 o = (Evas_Object_Text *)(obj->object_data);
846 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
849 if (r) *r = o->cur.glow2.r;
850 if (g) *g = o->cur.glow2.g;
851 if (b) *b = o->cur.glow2.b;
852 if (a) *a = o->cur.glow2.a;
858 * FIXME: To be fixed.
862 evas_object_text_outline_color_set(Evas_Object *obj, int r, int g, int b, int a)
866 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
869 o = (Evas_Object_Text *)(obj->object_data);
870 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
873 if ((o->cur.outline.r == r) && (o->cur.outline.g == g) &&
874 (o->cur.outline.b == b) && (o->cur.outline.a == a))
876 o->cur.outline.r = r;
877 o->cur.outline.g = g;
878 o->cur.outline.b = b;
879 o->cur.outline.a = a;
880 evas_object_change(obj);
886 * FIXME: To be fixed.
890 evas_object_text_outline_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
894 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
897 o = (Evas_Object_Text *)(obj->object_data);
898 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
901 if (r) *r = o->cur.outline.r;
902 if (g) *g = o->cur.outline.g;
903 if (b) *b = o->cur.outline.b;
904 if (a) *a = o->cur.outline.a;
910 * FIXME: To be fixed.
914 evas_object_text_style_pad_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
916 int sl = 0, sr = 0, st = 0, sb = 0;
919 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
922 o = (Evas_Object_Text *)(obj->object_data);
923 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
926 /* use temps to be certain we have initialized values */
927 evas_text_style_pad_get(o->cur.style, &sl, &sr, &st, &sb);
936 * @defgroup Evas_Font_Path_Group Font Path Functions
938 * Functions that edit the paths being used to load fonts.
942 * Removes all font paths loaded into memory for the given evas.
943 * @param e The given evas.
944 * @ingroup Evas_Font_Path_Group
947 evas_font_path_clear(Evas *e)
949 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
954 evas_stringshare_del(e->font_path->data);
955 e->font_path = evas_list_remove(e->font_path, e->font_path->data);
960 * Appends a font path to the list of font paths used by the given evas.
961 * @param e The given evas.
962 * @param path The new font path.
963 * @ingroup Evas_Font_Path_Group
966 evas_font_path_append(Evas *e, const char *path)
968 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
973 e->font_path = evas_list_append(e->font_path, evas_stringshare_add(path));
977 * Prepends a font path to the list of font paths used by the given evas.
978 * @param e The given evas.
979 * @param path The new font path.
980 * @ingroup Evas_Font_Path_Group
983 evas_font_path_prepend(Evas *e, const char *path)
985 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
990 e->font_path = evas_list_prepend(e->font_path, evas_stringshare_add(path));
994 * Retrieves the list of font paths used by the given evas.
995 * @param e The given evas.
996 * @return The list of font paths used.
997 * @ingroup Evas_Font_Path_Group
999 EAPI const Evas_List *
1000 evas_font_path_list(const Evas *e)
1002 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1005 return e->font_path;
1009 evas_font_object_rehint(Evas_Object *obj)
1011 if (obj->smart.smart)
1013 const Evas_Object_List *l3;
1015 for (l3 = evas_object_smart_members_get_direct(obj); l3; l3 = l3->next)
1017 obj = (Evas_Object *)l3;
1018 evas_font_object_rehint(obj);
1023 if (!strcmp(obj->type, "text"))
1024 _evas_object_text_rehint(obj);
1025 if (!strcmp(obj->type, "textblock"))
1026 _evas_object_textblock_rehint(obj);
1031 evas_font_hinting_set(Evas *e, Evas_Font_Hinting_Flags hinting)
1033 Evas_Object_List *l;
1035 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1038 if (e->hinting == hinting) return;
1039 e->hinting = hinting;
1040 for (l = (Evas_Object_List *)e->layers; l; l = l->next)
1042 Evas_Object_List *l2;
1045 lay = (Evas_Layer *)l;
1046 for (l2 = (Evas_Object_List *)lay->objects; l2; l2 = l2->next)
1050 obj = (Evas_Object *)l2;
1051 evas_font_object_rehint(obj);
1056 EAPI Evas_Font_Hinting_Flags
1057 evas_font_hinting_get(const Evas *e)
1059 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1060 return EVAS_FONT_HINTING_BYTECODE;
1066 evas_font_hinting_can_hint(const Evas *e, Evas_Font_Hinting_Flags hinting)
1068 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1071 if (e->engine.func->font_hinting_can_hint)
1072 return e->engine.func->font_hinting_can_hint(e->engine.data.output,
1084 * FIXME: To be fixed.
1088 evas_font_cache_flush(Evas *e)
1090 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1094 e->engine.func->font_cache_flush(e->engine.data.output);
1100 * FIXME: To be fixed.
1104 evas_font_cache_set(Evas *e, int size)
1106 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1110 if (size < 0) size = 0;
1111 e->engine.func->font_cache_set(e->engine.data.output, size);
1117 * FIXME: To be fixed.
1121 evas_font_cache_get(const Evas *e)
1123 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1127 return e->engine.func->font_cache_get(e->engine.data.output);
1133 * FIXME: To be fixed.
1137 evas_font_available_list(const Evas *e)
1139 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1143 return evas_font_dir_available_list(e);
1149 * FIXME: To be fixed.
1153 evas_font_available_list_free(Evas *e, Evas_List *available)
1155 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1159 return evas_font_dir_available_list_free(available);
1165 * FIXME: To be fixed.
1169 evas_string_char_next_get(const char *str, int pos, int *decoded)
1173 if (decoded) *decoded = 0;
1175 if (pos < 0) return 0;
1177 d = evas_common_font_utf8_get_next((unsigned char *)str, &p);
1178 if (decoded) *decoded = d;
1185 * FIXME: To be fixed.
1189 evas_string_char_prev_get(const char *str, int pos, int *decoded)
1193 if (decoded) *decoded = 0;
1195 if (pos < 1) return 0;
1197 d = evas_common_font_utf8_get_prev((unsigned char *)str, &p);
1198 if (decoded) *decoded = d;
1203 * Get the minimum padding a style adds to the text.
1204 * @param style The style to determine padding.
1205 * @param l Pointer to the current left padding value
1206 * @param r Pointer to the current right padding value
1207 * @param t Pointer to the current top padding value
1208 * @param b Pointer to the current bottom padding value
1211 evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b)
1227 if (style == EVAS_TEXT_STYLE_SHADOW)
1232 else if (style == EVAS_TEXT_STYLE_OUTLINE)
1239 else if (style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
1246 else if (style == EVAS_TEXT_STYLE_GLOW)
1253 else if (style == EVAS_TEXT_STYLE_OUTLINE_SHADOW)
1260 else if (style == EVAS_TEXT_STYLE_FAR_SHADOW)
1265 else if (style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)
1272 else if (style == EVAS_TEXT_STYLE_SOFT_SHADOW)
1279 else if (style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)
1291 /* all nice and private */
1293 evas_object_text_init(Evas_Object *obj)
1295 /* alloc text ob, setup methods and default values */
1296 obj->object_data = evas_object_text_new();
1297 /* set up default settings for this kind of object */
1298 obj->cur.color.r = 255;
1299 obj->cur.color.g = 255;
1300 obj->cur.color.b = 255;
1301 obj->cur.color.a = 255;
1302 obj->cur.geometry.x = 0.0;
1303 obj->cur.geometry.y = 0.0;
1304 obj->cur.geometry.w = 0.0;
1305 obj->cur.geometry.h = 0.0;
1307 /* set up object-specific settings */
1308 obj->prev = obj->cur;
1309 /* set up methods (compulsory) */
1310 obj->func = &object_func;
1315 evas_object_text_new(void)
1317 Evas_Object_Text *o;
1319 /* alloc obj private data */
1320 o = calloc(1, sizeof(Evas_Object_Text));
1321 o->magic = MAGIC_OBJ_TEXT;
1327 evas_object_text_free(Evas_Object *obj)
1329 Evas_Object_Text *o;
1331 /* frees private object data. very simple here */
1332 o = (Evas_Object_Text *)(obj->object_data);
1333 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1337 if (o->cur.text) evas_stringshare_del(o->cur.text);
1338 if (o->cur.font) evas_stringshare_del(o->cur.font);
1339 if (o->cur.source) evas_stringshare_del(o->cur.source);
1340 if (o->engine_data) evas_font_free(obj->layer->evas, o->engine_data);
1346 evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
1349 Evas_Object_Text *o;
1350 const char vals[5][5] =
1360 /* render object to surface with context, and offxet by x,y */
1361 o = (Evas_Object_Text *)(obj->object_data);
1362 evas_text_style_pad_get(o->cur.style, &sl, NULL, &st, NULL);
1363 ENFN->context_multiplier_unset(output, context);
1364 ENFN->context_render_op_set(output, context, obj->cur.render_op);
1366 ENFN->context_color_set(output,
1369 ENFN->rectangle_draw(output,
1372 obj->cur.cache.geometry.x + x,
1373 obj->cur.cache.geometry.y + y,
1374 obj->cur.cache.geometry.w,
1375 obj->cur.cache.geometry.h);
1378 #define COLOR_ONLY_SET(object, sub, col) \
1379 ENFN->context_color_set(output, context, \
1380 object->sub.col.r, \
1381 object->sub.col.g, \
1382 object->sub.col.b, \
1385 #define COLOR_SET(object, sub, col) \
1386 if (obj->cur.clipper)\
1387 ENFN->context_color_set(output, context, \
1388 ((int)object->sub.col.r * ((int)obj->cur.clipper->cur.cache.clip.r + 1)) >> 8, \
1389 ((int)object->sub.col.g * ((int)obj->cur.clipper->cur.cache.clip.g + 1)) >> 8, \
1390 ((int)object->sub.col.b * ((int)obj->cur.clipper->cur.cache.clip.b + 1)) >> 8, \
1391 ((int)object->sub.col.a * ((int)obj->cur.clipper->cur.cache.clip.a + 1)) >> 8); \
1393 ENFN->context_color_set(output, context, \
1394 object->sub.col.r, \
1395 object->sub.col.g, \
1396 object->sub.col.b, \
1399 #define COLOR_SET_AMUL(object, sub, col, amul) \
1400 if (obj->cur.clipper) \
1401 ENFN->context_color_set(output, context, \
1402 (((int)object->sub.col.r) * ((int)obj->cur.clipper->cur.cache.clip.r) * (amul)) / 65025, \
1403 (((int)object->sub.col.g) * ((int)obj->cur.clipper->cur.cache.clip.g) * (amul)) / 65025, \
1404 (((int)object->sub.col.b) * ((int)obj->cur.clipper->cur.cache.clip.b) * (amul)) / 65025, \
1405 (((int)object->sub.col.a) * ((int)obj->cur.clipper->cur.cache.clip.a) * (amul)) / 65025); \
1407 ENFN->context_color_set(output, context, \
1408 (((int)object->sub.col.r) * (amul)) / 255, \
1409 (((int)object->sub.col.g) * (amul)) / 255, \
1410 (((int)object->sub.col.b) * (amul)) / 255, \
1411 (((int)object->sub.col.a) * (amul)) / 255);
1414 #define DRAW_TEXT(ox, oy) \
1415 if ((o->engine_data) && (o->cur.text)) \
1416 ENFN->font_draw(output, \
1420 obj->cur.geometry.x + x + sl + ox, \
1421 obj->cur.geometry.y + y + st + oy + \
1423 (((o->max_ascent * obj->cur.geometry.h) / obj->cur.geometry.h) - 0.5), \
1424 obj->cur.geometry.w, \
1425 obj->cur.geometry.h, \
1426 obj->cur.geometry.w, \
1427 obj->cur.geometry.h, \
1430 #define DRAW_TEXT(ox, oy) \
1431 if ((o->engine_data) && (o->cur.text)) \
1432 ENFN->font_draw(output, \
1436 obj->cur.cache.geometry.x + x + sl + ox - \
1437 ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text), \
1438 obj->cur.cache.geometry.y + y + st + oy + \
1440 (((o->max_ascent * obj->cur.cache.geometry.h) / obj->cur.geometry.h) - 0.5), \
1441 obj->cur.cache.geometry.w, \
1442 obj->cur.cache.geometry.h, \
1443 obj->cur.geometry.w, \
1444 obj->cur.geometry.h, \
1448 if (o->cur.style == EVAS_TEXT_STYLE_SHADOW)
1450 COLOR_SET(o, cur, shadow);
1453 else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
1454 (o->cur.style == EVAS_TEXT_STYLE_FAR_SHADOW))
1456 COLOR_SET(o, cur, shadow);
1459 else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) ||
1460 (o->cur.style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW))
1462 for (j = 0; j < 5; j++)
1464 for (i = 0; i < 5; i++)
1466 if (vals[i][j] != 0)
1468 COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1474 else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_SHADOW)
1476 for (j = 0; j < 5; j++)
1478 for (i = 0; i < 5; i++)
1480 if (vals[i][j] != 0)
1482 COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1483 DRAW_TEXT(i - 1, j - 1);
1490 if (o->cur.style == EVAS_TEXT_STYLE_GLOW)
1492 for (j = 0; j < 5; j++)
1494 for (i = 0; i < 5; i++)
1496 if (vals[i][j] != 0)
1498 COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50);
1499 DRAW_TEXT(i - 2, j - 2);
1503 COLOR_SET(o, cur, glow2);
1511 if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE) ||
1512 (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
1513 (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW))
1515 COLOR_SET(o, cur, outline);
1521 else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
1523 for (j = 0; j < 5; j++)
1525 for (i = 0; i < 5; i++)
1527 if (((i != 2) || (j != 2)) && (vals[i][j] != 0))
1529 COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50);
1530 DRAW_TEXT(i - 2, j - 2);
1537 COLOR_ONLY_SET(obj, cur.cache, clip);
1542 evas_object_text_render_pre(Evas_Object *obj)
1544 Evas_Rectangles rects = { 0, 0, NULL };
1545 Evas_Object_Text *o;
1548 /* dont pre-render the obj twice! */
1549 if (obj->pre_render_done) return;
1550 obj->pre_render_done = 1;
1551 /* pre-render phase. this does anything an object needs to do just before */
1552 /* rendering. this could mean loading the image data, retrieving it from */
1553 /* elsewhere, decoding video etc. */
1554 /* then when this is done the object needs to figure if it changed and */
1555 /* if so what and where and add thr appropriate redraw rectangles */
1556 o = (Evas_Object_Text *)(obj->object_data);
1557 /* if someone is clipping this obj - go calculate the clipper */
1558 if (obj->cur.clipper)
1560 if (obj->cur.cache.clip.dirty)
1561 evas_object_clip_recalc(obj->cur.clipper);
1562 obj->cur.clipper->func->render_pre(obj->cur.clipper);
1564 /* now figure what changed and add draw rects */
1565 /* if it just became visible or invisible */
1566 is_v = evas_object_is_visible(obj);
1567 was_v = evas_object_was_visible(obj);
1570 evas_object_render_pre_visible_change(&rects, obj, is_v, was_v);
1573 /* its not visible - we accounted for it appearing or not so just abort */
1574 if (!is_v) goto done;
1575 /* clipper changed this is in addition to anything else for obj */
1576 evas_object_render_pre_clipper_change(&rects, obj);
1577 /* if we restacked (layer or just within a layer) and dont clip anyone */
1580 evas_object_render_pre_prev_cur_add(&rects, obj);
1583 /* if it changed color */
1584 if ((obj->cur.color.r != obj->prev.color.r) ||
1585 (obj->cur.color.g != obj->prev.color.g) ||
1586 (obj->cur.color.b != obj->prev.color.b) ||
1587 (obj->cur.color.a != obj->prev.color.a))
1589 evas_object_render_pre_prev_cur_add(&rects, obj);
1592 /* if it changed geometry - and obviously not visibility or color */
1593 /* caluclate differences since we have a constant color fill */
1594 /* we really only need to update the differences */
1595 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
1596 (obj->cur.geometry.y != obj->prev.geometry.y) ||
1597 (obj->cur.geometry.w != obj->prev.geometry.w) ||
1598 (obj->cur.geometry.h != obj->prev.geometry.h))
1600 evas_object_render_pre_prev_cur_add(&rects, obj);
1603 if (obj->cur.render_op != obj->prev.render_op)
1605 evas_object_render_pre_prev_cur_add(&rects, obj);
1610 if ((o->cur.size != o->prev.size) ||
1611 ((o->cur.font) && (o->prev.font) && (strcmp(o->cur.font, o->prev.font))) ||
1612 ((o->cur.font) && (!o->prev.font)) ||
1613 ((!o->cur.font) && (o->prev.font)) ||
1614 ((o->cur.text) && (o->prev.text) && (strcmp(o->cur.text, o->prev.text))) ||
1615 ((o->cur.text) && (!o->prev.text)) ||
1616 ((!o->cur.text) && (o->prev.text)) ||
1617 ((o->cur.style != o->prev.style)) ||
1618 ((o->cur.shadow.r != o->prev.shadow.r)) ||
1619 ((o->cur.shadow.g != o->prev.shadow.g)) ||
1620 ((o->cur.shadow.b != o->prev.shadow.b)) ||
1621 ((o->cur.shadow.a != o->prev.shadow.a)) ||
1622 ((o->cur.outline.r != o->prev.outline.r)) ||
1623 ((o->cur.outline.g != o->prev.outline.g)) ||
1624 ((o->cur.outline.b != o->prev.outline.b)) ||
1625 ((o->cur.outline.a != o->prev.outline.a)) ||
1626 ((o->cur.glow.r != o->prev.glow.r)) ||
1627 ((o->cur.glow.g != o->prev.glow.g)) ||
1628 ((o->cur.glow.b != o->prev.glow.b)) ||
1629 ((o->cur.glow.a != o->prev.glow.a)) ||
1630 ((o->cur.glow2.r != o->prev.glow2.r)) ||
1631 ((o->cur.glow2.g != o->prev.glow2.g)) ||
1632 ((o->cur.glow2.b != o->prev.glow2.b)) ||
1633 ((o->cur.glow2.a != o->prev.glow2.a)))
1635 evas_object_render_pre_prev_cur_add(&rects, obj);
1640 evas_object_render_pre_effect_updates(&rects, obj, is_v, was_v);
1644 evas_object_text_render_post(Evas_Object *obj)
1646 Evas_Object_Text *o;
1648 /* this moves the current data to the previous state parts of the object */
1649 /* in whatever way is safest for the object. also if we don't need object */
1650 /* data anymore we can free it if the object deems this is a good idea */
1651 o = (Evas_Object_Text *)(obj->object_data);
1652 /* remove those pesky changes */
1653 while (obj->clip.changes)
1657 r = (Evas_Rectangle *)obj->clip.changes->data;
1658 obj->clip.changes = evas_list_remove(obj->clip.changes, r);
1661 /* move cur to prev safely for object data */
1662 obj->prev = obj->cur;
1668 evas_object_text_is_opaque(Evas_Object *obj)
1670 Evas_Object_Text *o;
1672 /* this returns 1 if the internal object data implies that the object is */
1673 /* currently fulyl opque over the entire gradient it occupies */
1674 o = (Evas_Object_Text *)(obj->object_data);
1679 evas_object_text_was_opaque(Evas_Object *obj)
1681 Evas_Object_Text *o;
1683 /* this returns 1 if the internal object data implies that the object was */
1684 /* currently fulyl opque over the entire gradient it occupies */
1685 o = (Evas_Object_Text *)(obj->object_data);
1690 _evas_object_text_rehint(Evas_Object *obj)
1692 Evas_Object_Text *o;
1695 o = (Evas_Object_Text *)(obj->object_data);
1696 if (!o->engine_data) return;
1697 evas_font_load_hinting_set(obj->layer->evas, o->engine_data,
1698 obj->layer->evas->hinting);
1699 was = evas_object_is_in_output_rect(obj,
1700 obj->layer->evas->pointer.x,
1701 obj->layer->evas->pointer.y, 1, 1);
1703 o->prev.text = NULL;
1704 if ((o->engine_data) && (o->cur.text))
1707 int l = 0, r = 0, t = 0, b = 0;
1709 ENFN->font_string_size_get(ENDT,
1713 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
1714 obj->cur.geometry.w = w + l + r;
1715 obj->cur.geometry.h = h + t + b;
1716 //// obj->cur.cache.geometry.validity = 0;
1722 evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b);
1723 obj->cur.geometry.w = 0;
1724 obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b;
1725 //// obj->cur.cache.geometry.validity = 0;
1728 evas_object_change(obj);
1729 evas_object_coords_recalc(obj);
1730 is = evas_object_is_in_output_rect(obj,
1731 obj->layer->evas->pointer.x,
1732 obj->layer->evas->pointer.y, 1, 1);
1733 if ((is || was) && obj->cur.visible)
1734 evas_event_feed_mouse_move(obj->layer->evas,
1735 obj->layer->evas->pointer.x,
1736 obj->layer->evas->pointer.y,
1737 obj->layer->evas->last_timestamp,
1739 evas_object_inform_call_resize(obj);