move around - flatter.
[profile/ivi/evas.git] / src / lib / canvas / evas_object_text.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 /* save typing */
5 #define ENFN obj->layer->evas->engine.func
6 #define ENDT obj->layer->evas->engine.data.output
7
8 /* private magic number for text objects */
9 static const char o_type[] = "text";
10
11 /* private struct for text object internal data */
12 typedef struct _Evas_Object_Text      Evas_Object_Text;
13
14 struct _Evas_Object_Text
15 {
16    DATA32               magic;
17
18    struct {
19       const char       *text;
20       const char       *font;
21       const char       *source;
22       Evas_Font_Size    size;
23       struct {
24          unsigned char  r, g, b, a;
25       } outline, shadow, glow, glow2;
26
27       unsigned char     style;
28    } cur, prev;
29
30    float                ascent, descent;
31    float                max_ascent, max_descent;
32
33    void                *engine_data;
34    
35    char                 changed : 1;
36 };
37
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);
45
46 static int evas_object_text_is_opaque(Evas_Object *obj);
47 static int evas_object_text_was_opaque(Evas_Object *obj);
48
49 static const Evas_Object_Func object_func =
50 {
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 */
57      NULL,
58      NULL,
59      NULL,
60      NULL,
61      evas_object_text_is_opaque,
62      evas_object_text_was_opaque,
63      NULL,
64      NULL,
65      NULL
66 };
67
68 /* the actual api call to add a rect */
69 /* it has no other api calls as all properties are standard */
70
71 /**
72  * Creates a new text @c Evas_Object on the provided @c Evas canvas.
73  *
74  * @param e The @c Evas canvas to create the text object upon.
75  *
76  * @see evas_object_text_font_source_set
77  * @see evas_object_text_font_set
78  * @see evas_object_text_text_set
79  *
80  * @returns NULL on error, A pointer to a new @c Evas_Object on success.
81  */
82 EAPI Evas_Object *
83 evas_object_text_add(Evas *e)
84 {
85    Evas_Object *obj;
86
87    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
88    return NULL;
89    MAGIC_CHECK_END();
90    obj = evas_object_new();
91    evas_object_text_init(obj);
92    evas_object_inject(obj, e);
93    return obj;
94 }
95
96 /**
97  * To be documented.
98  *
99  * FIXME: To be fixed.
100  *
101  */
102 EAPI void
103 evas_object_text_font_source_set(Evas_Object *obj, const char *font_source)
104 {
105    Evas_Object_Text *o;
106
107    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
108    return;
109    MAGIC_CHECK_END();
110    o = (Evas_Object_Text *)(obj->object_data);
111    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
112    return;
113    MAGIC_CHECK_END();
114    
115    if ((o->cur.source) && (font_source) &&
116        (!strcmp(o->cur.source, font_source)))
117      return;
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;
121 }
122
123 /**
124  * To be documented.
125  *
126  * FIXME: To be fixed.
127  *
128  */
129 EAPI const char *
130 evas_object_text_font_source_get(const Evas_Object *obj)
131 {
132    Evas_Object_Text *o;
133
134    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
135    return NULL;
136    MAGIC_CHECK_END();
137    o = (Evas_Object_Text *)(obj->object_data);
138    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
139    return NULL;
140    MAGIC_CHECK_END();
141    return o->cur.source;
142 }
143
144 /**
145  * To be documented.
146  *
147  * FIXME: To be fixed.
148  *
149  */
150 EAPI void
151 evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size size)
152 {
153    Evas_Object_Text *o;
154    int l = 0, r = 0, t = 0, b = 0;
155    int is, was = 0, pass = 0;
156    int same_font = 0;
157
158    if (!font) return;
159    if (size <= 0) return;
160    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
161    return;
162    MAGIC_CHECK_END();
163    o = (Evas_Object_Text *)(obj->object_data);
164    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
165    return;
166    MAGIC_CHECK_END();
167    
168    if ((o->cur.font) && (font) && (!strcmp(o->cur.font, font)))
169      {
170         same_font = 1;
171         if (size == o->cur.size) return;
172      }
173    if (obj->layer->evas->events_frozen <= 0)
174      {
175         pass = evas_event_passes_through(obj);
176         if (!pass)
177           was = evas_object_is_in_output_rect(obj,
178                                               obj->layer->evas->pointer.x,
179                                               obj->layer->evas->pointer.y, 1, 1);
180      }
181    /* DO IT */
182    if (o->engine_data)
183      {
184         evas_font_free(obj->layer->evas, o->engine_data);
185         o->engine_data = NULL;
186      }
187    o->engine_data = evas_font_load(obj->layer->evas, font, o->cur.source, size);
188    if (!same_font)
189      {
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;
193         o->prev.font = NULL;
194      }
195    o->cur.size = size;
196    evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
197    if ((o->engine_data) && (o->cur.text))
198      {
199         int w, h;
200
201         ENFN->font_string_size_get(ENDT,
202                                    o->engine_data,
203                                    o->cur.text,
204                                    &w, &h);
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;
212      }
213    else
214      {
215         if (o->engine_data)
216           {
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);
221           }
222         else
223           {
224              o->ascent = 0;
225              o->descent = 0;
226              o->max_ascent = 0;
227              o->max_descent = 0;
228           }
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;
232      }
233    o->changed = 1;
234    evas_object_change(obj);
235    evas_object_coords_recalc(obj);
236    if (obj->layer->evas->events_frozen <= 0)
237      {
238         if (!pass)
239           {
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,
248                                           NULL);
249           }
250      }
251    evas_object_inform_call_resize(obj);
252 }
253
254 /**
255  * Query evas for font information of a text @c Evas_Object.
256  *
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.
261  * 
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).
265  */
266 EAPI void
267 evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_Size *size)
268 {
269    Evas_Object_Text *o;
270
271    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
272    if (font) *font = "";
273    if (size) *size = 0;
274    return;
275    MAGIC_CHECK_END();
276    o = (Evas_Object_Text *)(obj->object_data);
277    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
278    if (font) *font = "";
279    if (size) *size = 0;
280    return;
281    MAGIC_CHECK_END();
282    if (font) *font = o->cur.font;
283    if (size) *size = o->cur.size;
284 }
285
286 /**
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.
290  */
291 EAPI void
292 evas_object_text_text_set(Evas_Object *obj, const char *text)
293 {
294    Evas_Object_Text *o;
295    int is, was;
296
297    if (!text) text = "";
298    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
299    return;
300    MAGIC_CHECK_END();
301    o = (Evas_Object_Text *)(obj->object_data);
302    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
303    return;
304    MAGIC_CHECK_END();
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);
309    /* DO II */
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;
313    o->prev.text = NULL;
314    if ((o->engine_data) && (o->cur.text))
315      {
316         int w, h;
317         int l = 0, r = 0, t = 0, b = 0;
318
319         ENFN->font_string_size_get(ENDT,
320                                    o->engine_data,
321                                    o->cur.text,
322                                    &w, &h);
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;
327      }
328    else
329      {
330         int t = 0, b = 0;
331
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;
336      }
337    o->changed = 1;
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,
348                                 NULL);
349    evas_object_inform_call_resize(obj);
350 }
351
352 /**
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.
356  */
357 EAPI const char *
358 evas_object_text_text_get(const Evas_Object *obj)
359 {
360    Evas_Object_Text *o;
361
362    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
363    return NULL;
364    MAGIC_CHECK_END();
365    o = (Evas_Object_Text *)(obj->object_data);
366    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
367    return NULL;
368    MAGIC_CHECK_END();
369    return o->cur.text;
370 }
371
372 /**
373  * To be documented.
374  *
375  * FIXME: To be fixed.
376  *
377  */
378 EAPI Evas_Coord
379 evas_object_text_ascent_get(const Evas_Object *obj)
380 {
381    Evas_Object_Text *o;
382
383    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
384    return 0;
385    MAGIC_CHECK_END();
386    o = (Evas_Object_Text *)(obj->object_data);
387    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
388    return 0;
389    MAGIC_CHECK_END();
390    return o->ascent;
391 }
392
393 /**
394  * To be documented.
395  *
396  * FIXME: To be fixed.
397  *
398  */
399 EAPI Evas_Coord
400 evas_object_text_descent_get(const Evas_Object *obj)
401 {
402    Evas_Object_Text *o;
403
404    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
405    return 0;
406    MAGIC_CHECK_END();
407    o = (Evas_Object_Text *)(obj->object_data);
408    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
409    return 0;
410    MAGIC_CHECK_END();
411    return o->descent;
412 }
413
414 /**
415  * To be documented.
416  *
417  * FIXME: To be fixed.
418  *
419  */
420 EAPI Evas_Coord
421 evas_object_text_max_ascent_get(const Evas_Object *obj)
422 {
423    Evas_Object_Text *o;
424
425    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
426    return 0;
427    MAGIC_CHECK_END();
428    o = (Evas_Object_Text *)(obj->object_data);
429    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
430    return 0;
431    MAGIC_CHECK_END();
432    return o->max_ascent;
433 }
434
435 /**
436  * To be documented.
437  *
438  * FIXME: To be fixed.
439  *
440  */
441 EAPI Evas_Coord
442 evas_object_text_max_descent_get(const Evas_Object *obj)
443 {
444    Evas_Object_Text *o;
445
446    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
447    return 0;
448    MAGIC_CHECK_END();
449    o = (Evas_Object_Text *)(obj->object_data);
450    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
451    return 0;
452    MAGIC_CHECK_END();
453    return o->max_descent;
454 }
455
456 /**
457  * To be documented.
458  *
459  * FIXME: To be fixed.
460  *
461  */
462 EAPI Evas_Coord
463 evas_object_text_inset_get(const Evas_Object *obj)
464 {
465    Evas_Object_Text *o;
466
467    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
468    return 0;
469    MAGIC_CHECK_END();
470    o = (Evas_Object_Text *)(obj->object_data);
471    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
472    return 0;
473    MAGIC_CHECK_END();
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);
477 }
478
479 /**
480  * To be documented.
481  *
482  * FIXME: To be fixed.
483  *
484  */
485 EAPI Evas_Coord
486 evas_object_text_horiz_advance_get(const Evas_Object *obj)
487 {
488    Evas_Object_Text *o;
489
490    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
491    return 0;
492    MAGIC_CHECK_END();
493    o = (Evas_Object_Text *)(obj->object_data);
494    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
495    return 0;
496    MAGIC_CHECK_END();
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);
500 }
501
502 /**
503  * To be documented.
504  *
505  * FIXME: To be fixed.
506  *
507  */
508 EAPI Evas_Coord
509 evas_object_text_vert_advance_get(const Evas_Object *obj)
510 {
511    Evas_Object_Text *o;
512
513    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
514    return 0;
515    MAGIC_CHECK_END();
516    o = (Evas_Object_Text *)(obj->object_data);
517    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
518    return 0;
519    MAGIC_CHECK_END();
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);
523 }
524
525 /**
526  * Retrieve position and dimension information of a character within a text @c Evas_Object.
527  *
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
532  * parameter.
533  *
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).
540  *
541  * @returns 0 on error, 1 on success.
542  */
543 EAPI int
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)
545 {
546    Evas_Object_Text *o;
547    int l = 0, r = 0, t = 0, b = 0;
548    int ret, x = 0, y = 0, w = 0, h = 0;
549    int inset;
550
551    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
552    return 0;
553    MAGIC_CHECK_END();
554    o = (Evas_Object_Text *)(obj->object_data);
555    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
556    return 0;
557    MAGIC_CHECK_END();
558    if (!o->engine_data) return 0;
559    if (!o->cur.text) return 0;
560    inset =
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,
563                                                              pos,
564                                                              &x, &y,
565                                                              &w, &h);
566    evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
567    y += o->max_ascent - t;
568    x -= inset + l;
569    if (x < 0)
570      {
571         w += x;
572         x = 0;
573      }
574    if (x + w > obj->cur.geometry.w) w = obj->cur.geometry.w - x;
575    if (w < 0) w = 0;
576    if (y < 0)
577      {
578         h += y;
579         y = 0;
580      }
581    if (y + h > obj->cur.geometry.h) h = obj->cur.geometry.h - y;
582    if (h < 0) h = 0;
583    if (cx) *cx = x;
584    if (cy) *cy = y;
585    if (cw) *cw = w + l + r;
586    if (ch) *ch = h + t + b;
587    return ret;
588 }
589
590 /**
591  * To be documented.
592  *
593  * FIXME: To be fixed.
594  *
595  */
596 EAPI int
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)
598 {
599    Evas_Object_Text *o;
600    int l = 0, r = 0, t = 0, b = 0;
601    int ret, rx = 0, ry = 0, rw = 0, rh = 0;
602    int inset;
603
604    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
605    return -1;
606    MAGIC_CHECK_END();
607    o = (Evas_Object_Text *)(obj->object_data);
608    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
609    return -1;
610    MAGIC_CHECK_END();
611    if (!o->engine_data) return -1;
612    if (!o->cur.text) return -1;
613    inset =
614      ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
615    ret = ENFN->font_char_at_coords_get(ENDT,
616                                        o->engine_data,
617                                        o->cur.text,
618                                        x + inset,
619                                        y - o->max_ascent,
620                                        &rx, &ry,
621                                        &rw, &rh);
622    evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
623    ry += o->max_ascent - t;
624    rx -= inset + l;
625    if (rx < 0)
626      {
627         rw += rx;
628         rx = 0;
629      }
630    if (rx + rw > obj->cur.geometry.w) rw = obj->cur.geometry.w - rx;
631    if (rw < 0) rw = 0;
632    if (ry < 0)
633      {
634         rh += ry;
635         ry = 0;
636      }
637    if (ry + rh > obj->cur.geometry.h) rh = obj->cur.geometry.h - ry;
638    if (rh < 0) rh = 0;
639    if (cx) *cx = rx;
640    if (cy) *cy = ry;
641    if (cw) *cw = rw + l + r;
642    if (ch) *ch = rh + t + b;
643    return ret;
644 }
645
646 /**
647  * To be documented.
648  *
649  * FIXME: To be fixed.
650  *
651  */
652 EAPI void
653 evas_object_text_style_set(Evas_Object *obj, Evas_Text_Style_Type style)
654 {
655    Evas_Object_Text *o;
656    int pl = 0, pr = 0, pt = 0, pb = 0, l = 0, r = 0, t = 0, b = 0;
657
658    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
659    return;
660    MAGIC_CHECK_END();
661    o = (Evas_Object_Text *)(obj->object_data);
662    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
663    return;
664    MAGIC_CHECK_END();
665    if (o->cur.style == style)
666      return;
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);
670    if (o->cur.text)
671      obj->cur.geometry.w += (l - pl) + (r - pr);
672    else
673      obj->cur.geometry.w = 0;
674    obj->cur.geometry.h += (t - pt) + (b - pb);
675    evas_object_change(obj);
676 }
677
678 /**
679  * To be documented.
680  *
681  * FIXME: To be fixed.
682  *
683  */
684 EAPI Evas_Text_Style_Type
685 evas_object_text_style_get(const Evas_Object *obj)
686 {
687    Evas_Object_Text *o;
688
689    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
690    return EVAS_TEXT_STYLE_PLAIN;
691    MAGIC_CHECK_END();
692    o = (Evas_Object_Text *)(obj->object_data);
693    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
694    return EVAS_TEXT_STYLE_PLAIN;
695    MAGIC_CHECK_END();
696    return o->cur.style;
697 }
698
699 /**
700  * To be documented.
701  *
702  * FIXME: To be fixed.
703  *
704  */
705 EAPI void
706 evas_object_text_shadow_color_set(Evas_Object *obj, int r, int g, int b, int a)
707 {
708    Evas_Object_Text *o;
709
710    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
711    return;
712    MAGIC_CHECK_END();
713    o = (Evas_Object_Text *)(obj->object_data);
714    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
715    return;
716    MAGIC_CHECK_END();
717    if ((o->cur.shadow.r == r) && (o->cur.shadow.g == g) &&
718        (o->cur.shadow.b == b) && (o->cur.shadow.a == a))
719      return;
720    o->cur.shadow.r = r;
721    o->cur.shadow.g = g;
722    o->cur.shadow.b = b;
723    o->cur.shadow.a = a;
724    evas_object_change(obj);
725 }
726
727 /**
728  * To be documented.
729  *
730  * FIXME: To be fixed.
731  *
732  */
733 EAPI void
734 evas_object_text_shadow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
735 {
736    Evas_Object_Text *o;
737
738    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
739    return;
740    MAGIC_CHECK_END();
741    o = (Evas_Object_Text *)(obj->object_data);
742    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
743    return;
744    MAGIC_CHECK_END();
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;
749 }
750
751 /**
752  * To be documented.
753  *
754  * FIXME: To be fixed.
755  *
756  */
757 EAPI void
758 evas_object_text_glow_color_set(Evas_Object *obj, int r, int g, int b, int a)
759 {
760    Evas_Object_Text *o;
761
762    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
763    return;
764    MAGIC_CHECK_END();
765    o = (Evas_Object_Text *)(obj->object_data);
766    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
767    return;
768    MAGIC_CHECK_END();
769    if ((o->cur.glow.r == r) && (o->cur.glow.g == g) &&
770        (o->cur.glow.b == b) && (o->cur.glow.a == a))
771      return;
772    o->cur.glow.r = r;
773    o->cur.glow.g = g;
774    o->cur.glow.b = b;
775    o->cur.glow.a = a;
776    evas_object_change(obj);
777 }
778
779 /**
780  * To be documented.
781  *
782  * FIXME: To be fixed.
783  *
784  */
785 EAPI void
786 evas_object_text_glow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
787 {
788    Evas_Object_Text *o;
789
790    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
791    return;
792    MAGIC_CHECK_END();
793    o = (Evas_Object_Text *)(obj->object_data);
794    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
795    return;
796    MAGIC_CHECK_END();
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;
801 }
802
803 /**
804  * To be documented.
805  *
806  * FIXME: To be fixed.
807  *
808  */
809 EAPI void
810 evas_object_text_glow2_color_set(Evas_Object *obj, int r, int g, int b, int a)
811 {
812    Evas_Object_Text *o;
813
814    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
815    return;
816    MAGIC_CHECK_END();
817    o = (Evas_Object_Text *)(obj->object_data);
818    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
819    return;
820    MAGIC_CHECK_END();
821    if ((o->cur.glow2.r == r) && (o->cur.glow2.g == g) &&
822        (o->cur.glow2.b == b) && (o->cur.glow2.a == a))
823      return;
824    o->cur.glow2.r = r;
825    o->cur.glow2.g = g;
826    o->cur.glow2.b = b;
827    o->cur.glow2.a = a;
828    evas_object_change(obj);
829 }
830
831 /**
832  * To be documented.
833  *
834  * FIXME: To be fixed.
835  *
836  */
837 EAPI void
838 evas_object_text_glow2_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
839 {
840    Evas_Object_Text *o;
841
842    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
843    return;
844    MAGIC_CHECK_END();
845    o = (Evas_Object_Text *)(obj->object_data);
846    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
847    return;
848    MAGIC_CHECK_END();
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;
853 }
854
855 /**
856  * To be documented.
857  *
858  * FIXME: To be fixed.
859  *
860  */
861 EAPI void
862 evas_object_text_outline_color_set(Evas_Object *obj, int r, int g, int b, int a)
863 {
864    Evas_Object_Text *o;
865
866    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
867    return;
868    MAGIC_CHECK_END();
869    o = (Evas_Object_Text *)(obj->object_data);
870    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
871    return;
872    MAGIC_CHECK_END();
873    if ((o->cur.outline.r == r) && (o->cur.outline.g == g) &&
874        (o->cur.outline.b == b) && (o->cur.outline.a == a))
875      return;
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);
881 }
882
883 /**
884  * To be documented.
885  *
886  * FIXME: To be fixed.
887  *
888  */
889 EAPI void
890 evas_object_text_outline_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
891 {
892    Evas_Object_Text *o;
893
894    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
895    return;
896    MAGIC_CHECK_END();
897    o = (Evas_Object_Text *)(obj->object_data);
898    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
899    return;
900    MAGIC_CHECK_END();
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;
905 }
906
907 /**
908  * To be documented.
909  *
910  * FIXME: To be fixed.
911  *
912  */
913 EAPI void
914 evas_object_text_style_pad_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
915 {
916    int sl = 0, sr = 0, st = 0, sb = 0;
917    Evas_Object_Text *o;
918
919    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
920    return;
921    MAGIC_CHECK_END();
922    o = (Evas_Object_Text *)(obj->object_data);
923    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
924    return;
925    MAGIC_CHECK_END();
926    /* use temps to be certain we have initialized values */
927    evas_text_style_pad_get(o->cur.style, &sl, &sr, &st, &sb);
928    if (l) *l = sl;
929    if (r) *r = sr;
930    if (t) *t = st;
931    if (b) *b = sb;
932 }
933
934
935 /**
936  * @defgroup Evas_Font_Path_Group Font Path Functions
937  *
938  * Functions that edit the paths being used to load fonts.
939  */
940
941 /**
942  * Removes all font paths loaded into memory for the given evas.
943  * @param   e The given evas.
944  * @ingroup Evas_Font_Path_Group
945  */
946 EAPI void
947 evas_font_path_clear(Evas *e)
948 {
949    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
950    return;
951    MAGIC_CHECK_END();
952    while (e->font_path)
953      {
954         evas_stringshare_del(e->font_path->data);
955         e->font_path = evas_list_remove(e->font_path, e->font_path->data);
956      }
957 }
958
959 /**
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
964  */
965 EAPI void
966 evas_font_path_append(Evas *e, const char *path)
967 {
968    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
969    return;
970    MAGIC_CHECK_END();
971    if (!path) return;
972
973    e->font_path = evas_list_append(e->font_path, evas_stringshare_add(path));
974 }
975
976 /**
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
981  */
982 EAPI void
983 evas_font_path_prepend(Evas *e, const char *path)
984 {
985    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
986    return;
987    MAGIC_CHECK_END();
988    
989    if (!path) return;
990    e->font_path = evas_list_prepend(e->font_path, evas_stringshare_add(path));
991 }
992
993 /**
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
998  */
999 EAPI const Evas_List *
1000 evas_font_path_list(const Evas *e)
1001 {
1002    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1003    return NULL;
1004    MAGIC_CHECK_END();
1005    return e->font_path;
1006 }
1007
1008 static void
1009 evas_font_object_rehint(Evas_Object *obj)
1010 {
1011    if (obj->smart.smart)
1012      {
1013         const Evas_Object_List *l3;
1014         
1015         for (l3 = evas_object_smart_members_get_direct(obj); l3; l3 = l3->next)
1016           {
1017              obj = (Evas_Object *)l3;
1018              evas_font_object_rehint(obj);
1019           }
1020      }
1021    else
1022      {
1023         if (!strcmp(obj->type, "text"))
1024           _evas_object_text_rehint(obj);
1025         if (!strcmp(obj->type, "textblock"))
1026           _evas_object_textblock_rehint(obj);
1027      }
1028 }
1029
1030 EAPI void
1031 evas_font_hinting_set(Evas *e, Evas_Font_Hinting_Flags hinting)
1032 {
1033    Evas_Object_List *l;
1034    
1035    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1036    return;
1037    MAGIC_CHECK_END();
1038    if (e->hinting == hinting) return;
1039    e->hinting = hinting;
1040    for (l = (Evas_Object_List *)e->layers; l; l = l->next)
1041      {
1042         Evas_Object_List *l2;
1043         Evas_Layer *lay;
1044         
1045         lay = (Evas_Layer *)l;
1046         for (l2 = (Evas_Object_List *)lay->objects; l2; l2 = l2->next)
1047           {
1048              Evas_Object *obj;
1049              
1050              obj = (Evas_Object *)l2;
1051              evas_font_object_rehint(obj);
1052           }
1053      }
1054 }
1055
1056 EAPI Evas_Font_Hinting_Flags
1057 evas_font_hinting_get(const Evas *e)
1058 {
1059    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1060    return EVAS_FONT_HINTING_BYTECODE;
1061    MAGIC_CHECK_END();
1062    return e->hinting;
1063 }
1064
1065 EAPI Evas_Bool
1066 evas_font_hinting_can_hint(const Evas *e, Evas_Font_Hinting_Flags hinting)
1067 {
1068    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1069    return 0;
1070    MAGIC_CHECK_END();
1071    if (e->engine.func->font_hinting_can_hint)
1072      return e->engine.func->font_hinting_can_hint(e->engine.data.output,
1073                                                   hinting);
1074    return 0;
1075 }
1076
1077
1078
1079
1080
1081 /**
1082  * To be documented.
1083  *
1084  * FIXME: To be fixed.
1085  *
1086  */
1087 EAPI void
1088 evas_font_cache_flush(Evas *e)
1089 {
1090    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1091    return;
1092    MAGIC_CHECK_END();
1093
1094    e->engine.func->font_cache_flush(e->engine.data.output);
1095 }
1096
1097 /**
1098  * To be documented.
1099  *
1100  * FIXME: To be fixed.
1101  *
1102  */
1103 EAPI void
1104 evas_font_cache_set(Evas *e, int size)
1105 {
1106    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1107    return;
1108    MAGIC_CHECK_END();
1109
1110    if (size < 0) size = 0;
1111    e->engine.func->font_cache_set(e->engine.data.output, size);
1112 }
1113
1114 /**
1115  * To be documented.
1116  *
1117  * FIXME: To be fixed.
1118  *
1119  */
1120 EAPI int
1121 evas_font_cache_get(const Evas *e)
1122 {
1123    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1124    return 0;
1125    MAGIC_CHECK_END();
1126
1127    return e->engine.func->font_cache_get(e->engine.data.output);
1128 }
1129
1130 /**
1131  * To be documented.
1132  *
1133  * FIXME: To be fixed.
1134  *
1135  */
1136 EAPI Evas_List *
1137 evas_font_available_list(const Evas *e)
1138 {
1139    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1140    return NULL;
1141    MAGIC_CHECK_END();
1142
1143    return evas_font_dir_available_list(e);
1144 }
1145    
1146 /**
1147  * To be documented.
1148  *
1149  * FIXME: To be fixed.
1150  *
1151  */
1152 EAPI void
1153 evas_font_available_list_free(Evas *e, Evas_List *available)
1154
1155    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1156    return;
1157    MAGIC_CHECK_END();
1158
1159    return evas_font_dir_available_list_free(available); 
1160 }
1161
1162 /**
1163  * To be documented.
1164  *
1165  * FIXME: To be fixed.
1166  *
1167  */
1168 EAPI int
1169 evas_string_char_next_get(const char *str, int pos, int *decoded)
1170 {
1171    int p, d;
1172
1173    if (decoded) *decoded = 0;
1174    if (!str) return 0;
1175    if (pos < 0) return 0;
1176    p = pos;
1177    d = evas_common_font_utf8_get_next((unsigned char *)str, &p);
1178    if (decoded) *decoded = d;
1179    return p;
1180 }
1181
1182 /**
1183  * To be documented.
1184  *
1185  * FIXME: To be fixed.
1186  *
1187  */
1188 EAPI int
1189 evas_string_char_prev_get(const char *str, int pos, int *decoded)
1190 {
1191    int p, d;
1192
1193    if (decoded) *decoded = 0;
1194    if (!str) return 0;
1195    if (pos < 1) return 0;
1196    p = pos;
1197    d = evas_common_font_utf8_get_prev((unsigned char *)str, &p);
1198    if (decoded) *decoded = d;
1199    return p;
1200 }
1201
1202 /**
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
1209  */
1210 void
1211 evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b)
1212 {
1213    int sl, sr, st, sb;
1214
1215    if (l) sl = *l;
1216    else sl = 0;
1217
1218    if (r) sr = *r;
1219    else sr = 0;
1220
1221    if (t) st = *t;
1222    else st = 0;
1223
1224    if (b) sb = *b;
1225    else sb = 0;
1226
1227    if (style == EVAS_TEXT_STYLE_SHADOW)
1228      {
1229         if (sr < 1) sr = 1;
1230         if (sb < 1) sb = 1;
1231      }
1232    else if (style == EVAS_TEXT_STYLE_OUTLINE)
1233      {
1234         if (sl < 1) sl = 1;
1235         if (sr < 1) sr = 1;
1236         if (st < 1) st = 1;
1237         if (sb < 1) sb = 1;
1238      }
1239    else if (style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
1240      {
1241         if (sl < 2) sl = 2;
1242         if (sr < 2) sr = 2;
1243         if (st < 2) st = 2;
1244         if (sb < 2) sb = 2;
1245      }
1246    else if (style == EVAS_TEXT_STYLE_GLOW)
1247      {
1248         if (sl < 2) sl = 2;
1249         if (sr < 2) sr = 2;
1250         if (st < 2) st = 2;
1251         if (sb < 2) sb = 2;
1252      }
1253    else if (style == EVAS_TEXT_STYLE_OUTLINE_SHADOW)
1254      {
1255         if (sl < 1) sl = 1;
1256         if (sr < 2) sr = 2;
1257         if (st < 1) st = 1;
1258         if (sb < 2) sb = 2;
1259      }
1260    else if (style == EVAS_TEXT_STYLE_FAR_SHADOW)
1261      {
1262         if (sr < 2) sr = 2;
1263         if (sb < 2) sb = 2;
1264      }
1265    else if (style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)
1266      {
1267         if (sl < 1) sl = 1;
1268         if (sr < 3) sr = 3;
1269         if (st < 1) st = 1;
1270         if (sb < 3) sb = 3;
1271      }
1272    else if (style == EVAS_TEXT_STYLE_SOFT_SHADOW)
1273      {
1274         if (sl < 1) sl = 1;
1275         if (sr < 3) sr = 3;
1276         if (st < 1) st = 1;
1277         if (sb < 3) sb = 3;
1278      }
1279    else if (style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)
1280      {
1281         if (sr < 4) sr = 4;
1282         if (sb < 4) sb = 4;
1283      }
1284    
1285    if (l) *l = sl;
1286    if (r) *r = sr;
1287    if (t) *t = st;
1288    if (b) *b = sb;
1289 }
1290
1291 /* all nice and private */
1292 static void
1293 evas_object_text_init(Evas_Object *obj)
1294 {
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;
1306    obj->cur.layer = 0;
1307    /* set up object-specific settings */
1308    obj->prev = obj->cur;
1309    /* set up methods (compulsory) */
1310    obj->func = &object_func;
1311    obj->type = o_type;
1312 }
1313
1314 static void *
1315 evas_object_text_new(void)
1316 {
1317    Evas_Object_Text *o;
1318
1319    /* alloc obj private data */
1320    o = calloc(1, sizeof(Evas_Object_Text));
1321    o->magic = MAGIC_OBJ_TEXT;
1322    o->prev = o->cur;
1323    return o;
1324 }
1325
1326 static void
1327 evas_object_text_free(Evas_Object *obj)
1328 {
1329    Evas_Object_Text *o;
1330
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);
1334    return;
1335    MAGIC_CHECK_END();
1336    /* free obj */
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);
1341    o->magic = 0;
1342    free(o);
1343 }
1344
1345 static void
1346 evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
1347 {
1348    int i, j;
1349    Evas_Object_Text *o;
1350    const char vals[5][5] =
1351      {
1352           {0, 1, 2, 1, 0},
1353           {1, 3, 4, 3, 1},
1354           {2, 4, 5, 4, 2},
1355           {1, 3, 4, 3, 1},
1356           {0, 1, 2, 1, 0}
1357      };
1358    int sl = 0, st = 0;
1359
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);
1365 /*
1366    ENFN->context_color_set(output,
1367                                                     context,
1368                                                     230, 160, 30, 100);
1369    ENFN->rectangle_draw(output,
1370                                                  context,
1371                                                  surface,
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);
1376  */
1377
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, \
1383                                 object->sub.col.a);
1384
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); \
1392         else\
1393            ENFN->context_color_set(output, context, \
1394                                 object->sub.col.r, \
1395                                 object->sub.col.g, \
1396                                 object->sub.col.b, \
1397                                 object->sub.col.a);
1398
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); \
1406         else \
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);
1412           
1413
1414 #define DRAW_TEXT(ox, oy) \
1415    if ((o->engine_data) && (o->cur.text)) \
1416      ENFN->font_draw(output, \
1417                      context, \
1418                      surface, \
1419                      o->engine_data, \
1420                      obj->cur.geometry.x + x + sl + ox, \
1421                      obj->cur.geometry.y + y + st + oy + \
1422                      (int) \
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, \
1428                      o->cur.text);
1429 #if 0
1430 #define DRAW_TEXT(ox, oy) \
1431    if ((o->engine_data) && (o->cur.text)) \
1432      ENFN->font_draw(output, \
1433                      context, \
1434                      surface, \
1435                      o->engine_data, \
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 + \
1439                      (int) \
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, \
1445                      o->cur.text);
1446 #endif
1447    /* shadows */
1448    if (o->cur.style == EVAS_TEXT_STYLE_SHADOW)
1449      {
1450         COLOR_SET(o, cur, shadow);
1451         DRAW_TEXT(1, 1);
1452      }
1453    else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
1454             (o->cur.style == EVAS_TEXT_STYLE_FAR_SHADOW))
1455      {
1456         COLOR_SET(o, cur, shadow);
1457         DRAW_TEXT(2, 2);
1458      }
1459    else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) ||
1460             (o->cur.style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW))
1461      {
1462         for (j = 0; j < 5; j++)
1463           {
1464              for (i = 0; i < 5; i++)
1465                {
1466                   if (vals[i][j] != 0)
1467                     {
1468                        COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1469                        DRAW_TEXT(i, j);
1470                     }
1471                }
1472           }
1473      }
1474    else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_SHADOW)
1475      {
1476         for (j = 0; j < 5; j++)
1477           {
1478              for (i = 0; i < 5; i++)
1479                {
1480                   if (vals[i][j] != 0)
1481                     {
1482                        COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1483                        DRAW_TEXT(i - 1, j - 1);
1484                     }
1485                }
1486           }
1487      }
1488
1489    /* glows */
1490    if (o->cur.style == EVAS_TEXT_STYLE_GLOW)
1491      {
1492         for (j = 0; j < 5; j++)
1493           {
1494              for (i = 0; i < 5; i++)
1495                {
1496                   if (vals[i][j] != 0)
1497                     {
1498                        COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50);
1499                        DRAW_TEXT(i - 2, j - 2);
1500                     }
1501                }
1502           }
1503         COLOR_SET(o, cur, glow2);
1504         DRAW_TEXT(-1, 0);
1505         DRAW_TEXT(1, 0);
1506         DRAW_TEXT(0, -1);
1507         DRAW_TEXT(0, 1);
1508      }
1509
1510    /* outlines */
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))
1514      {
1515         COLOR_SET(o, cur, outline);
1516         DRAW_TEXT(-1, 0);
1517         DRAW_TEXT(1, 0);
1518         DRAW_TEXT(0, -1);
1519         DRAW_TEXT(0, 1);
1520      }
1521    else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
1522      {
1523         for (j = 0; j < 5; j++)
1524           {
1525              for (i = 0; i < 5; i++)
1526                {
1527                   if (((i != 2) || (j != 2)) && (vals[i][j] != 0))
1528                     {
1529                        COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50);
1530                        DRAW_TEXT(i - 2, j - 2);
1531                     }
1532                }
1533           }
1534      }
1535
1536    /* normal text */
1537    COLOR_ONLY_SET(obj, cur.cache, clip);
1538    DRAW_TEXT(0, 0);
1539 }
1540
1541 static void
1542 evas_object_text_render_pre(Evas_Object *obj)
1543 {
1544    Evas_Rectangles rects = { 0, 0, NULL };
1545    Evas_Object_Text *o;
1546    int is_v, was_v;
1547
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)
1559      {
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);
1563      }
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);
1568    if (is_v != was_v)
1569      {
1570         evas_object_render_pre_visible_change(&rects, obj, is_v, was_v);
1571         goto done;
1572      }
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 */
1578    if (obj->restack)
1579      {
1580         evas_object_render_pre_prev_cur_add(&rects, obj);
1581         goto done;
1582      }
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))
1588      {
1589         evas_object_render_pre_prev_cur_add(&rects, obj);
1590         goto done;
1591      }
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))
1599      {
1600         evas_object_render_pre_prev_cur_add(&rects, obj);
1601         goto done;
1602      }
1603    if (obj->cur.render_op != obj->prev.render_op)
1604      {
1605         evas_object_render_pre_prev_cur_add(&rects, obj);
1606         goto done;
1607      }
1608    if (o->changed)
1609      {
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)))
1634           {
1635              evas_object_render_pre_prev_cur_add(&rects, obj);
1636              goto done;
1637           }
1638      }
1639    done:
1640    evas_object_render_pre_effect_updates(&rects, obj, is_v, was_v);
1641 }
1642
1643 static void
1644 evas_object_text_render_post(Evas_Object *obj)
1645 {
1646    Evas_Object_Text *o;
1647
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)
1654      {
1655         Evas_Rectangle *r;
1656
1657         r = (Evas_Rectangle *)obj->clip.changes->data;
1658         obj->clip.changes = evas_list_remove(obj->clip.changes, r);
1659         free(r);
1660      }
1661    /* move cur to prev safely for object data */
1662    obj->prev = obj->cur;
1663    o->prev = o->cur;
1664    o->changed = 0;
1665 }
1666
1667 static int
1668 evas_object_text_is_opaque(Evas_Object *obj)
1669 {
1670    Evas_Object_Text *o;
1671
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);
1675    return 0;
1676 }
1677
1678 static int
1679 evas_object_text_was_opaque(Evas_Object *obj)
1680 {
1681    Evas_Object_Text *o;
1682
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);
1686    return 0;
1687 }
1688
1689 void
1690 _evas_object_text_rehint(Evas_Object *obj)
1691 {
1692    Evas_Object_Text *o;
1693    int is, was;
1694    
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);
1702    /* DO II */
1703    o->prev.text = NULL;
1704    if ((o->engine_data) && (o->cur.text))
1705      {
1706         int w, h;
1707         int l = 0, r = 0, t = 0, b = 0;
1708         
1709         ENFN->font_string_size_get(ENDT,
1710                                    o->engine_data,
1711                                    o->cur.text,
1712                                    &w, &h);
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;
1717      }
1718    else
1719      {
1720         int t = 0, b = 0;
1721         
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;
1726      }
1727    o->changed = 1;
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,
1738                                 NULL);
1739    evas_object_inform_call_resize(obj);
1740 }