summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_vg_private.h
blob: e2f393fec2593e565181f0f25b0cdab63cef0328 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef EVAS_VG_PRIVATE_H_
# define EVAS_VG_PRIVATE_H_

#include <Ector.h>

typedef struct _Efl_VG_Data                  Efl_VG_Data;
typedef struct _Efl_VG_Container_Data        Efl_VG_Container_Data;
typedef struct _Efl_VG_Gradient_Data         Efl_VG_Gradient_Data;
typedef struct _Efl_VG_Interpolation         Efl_VG_Interpolation;


typedef struct _Efl_Canvas_Vg_Data           Efl_Canvas_Vg_Data;

typedef struct _Evas_Cache_Vg_Entry          Evas_Cache_Vg_Entry;
typedef struct _Evas_Cache_Vg                Evas_Cache_Vg;

struct _Evas_Cache_Vg
{
   Eina_Hash             *vg_hash;
   Eina_Hash             *active;
   int                    ref;
};

struct _Evas_Cache_Vg_Entry
{
   char                 *hash_key;
   Eina_Stringshare     *file;
   Eina_Stringshare     *key;
   int                   w;
   int                   h;
   Efl_VG               *root;
   int                   ref;
};

typedef struct _User_Vg_Entry
{
   int                   w; // current surface width
   int                   h; // current surface height
   Efl_VG               *root;
}User_Vg_Entry; // holds the vg tree info set by the user

struct _Efl_Canvas_Vg_Data
{
   void                     *engine_data;
   Efl_VG                   *root;
   Evas_Cache_Vg_Entry      *vg_entry;
   User_Vg_Entry            *user_entry; // holds the user set vg tree
   Eina_Rect                 fill;
   Eina_Rect                 viewbox;
   unsigned int              width, height;
   Eina_Array                cleanup;
   double                    align_x, align_y;
   Efl_Canvas_Vg_Fill_Mode   fill_mode;
   Eina_Bool                 changed;
};

struct _Efl_VG_Data
{
   const char *name;

   Eina_Matrix3 *m;
   Efl_VG_Interpolation *intp;

   Efl_VG *mask;
   Ector_Renderer *renderer;

   void (*render_pre)(Eo *obj, Eina_Matrix3 *parent, Ector_Surface *s, void *data, Efl_VG_Data *nd);
   void *data;

   double x, y;
   int r, g, b, a;
   Efl_Gfx_Change_Flag flags;

   Eina_Bool visibility : 1;
   Eina_Bool changed : 1;
};

struct _Efl_VG_Container_Data
{
   Eina_List *children;

   Eina_Hash *names;
};

struct _Efl_VG_Gradient_Data
{
   // FIXME: Later on we should deduplicate it somehow (Using Ector ?).
   Efl_Gfx_Gradient_Stop *colors;
   unsigned int colors_count;

   Efl_Gfx_Gradient_Spread s;
};

struct _Efl_VG_Interpolation
{
   Eina_Quaternion rotation;
   Eina_Quaternion perspective;
   Eina_Point_3D translation;
   Eina_Point_3D scale;
   Eina_Point_3D skew;
};


void                        evas_cache_vg_init(void);
void                        evas_cache_vg_shutdown(void);
Evas_Cache_Vg_Entry*        evas_cache_vg_entry_find(const char *file, const char *key, int w, int h);
Efl_VG*                     evas_cache_vg_tree_get(Evas_Cache_Vg_Entry *svg_entry);
void                        evas_cache_vg_entry_del(Evas_Cache_Vg_Entry *svg_entry);
Vg_File_Data *              evas_cache_vg_file_info(const char *file, const char *key);

Eina_Bool                   evas_vg_save_to_file(Vg_File_Data *evg_data, const char *file, const char *key, const char *flags);

static inline Efl_VG_Data *
_evas_vg_render_pre(Efl_VG *child, Ector_Surface *s, Eina_Matrix3 *m)
{
   Efl_VG_Data *child_nd = NULL;

   // FIXME: Prevent infinite loop
   if (child)
     child_nd = efl_data_scope_get(child, EFL_VG_CLASS);
   if (child_nd)
     child_nd->render_pre(child, m, s, child_nd->data, child_nd);

   return child_nd;
}

static inline void
_efl_vg_changed(Eo *obj)
{
   Efl_Gfx_Path_Change_Event ev = { EFL_GFX_CHANGE_FLAG_FILL };
   efl_event_callback_call(obj, EFL_GFX_PATH_EVENT_CHANGED, &ev);
}

static inline void *
_efl_vg_realloc(void *from, unsigned int sz)
{
   void *result;

   result = sz > 0 ? realloc(from, sz) : NULL;
   if (!result) free(from);

   return result;
}

static inline void
_efl_vg_clean_object(Eo **obj)
{
   if (*obj) efl_unref(*obj);
   *obj = NULL;
}

#define EFL_VG_COMPUTE_MATRIX(Current, Parent, Nd)                      \
  Eina_Matrix3 *Current = Nd->m;                                        \
  Eina_Matrix3 _matrix_tmp;                                             \
                                                                        \
  if (Parent)                                                           \
    {                                                                   \
       if (Current)                                                     \
         {                                                              \
            eina_matrix3_compose(Parent, Current, &_matrix_tmp);        \
            Current = &_matrix_tmp;                                     \
         }                                                              \
       else                                                             \
         {                                                              \
            eina_matrix3_identity(&_matrix_tmp);                        \
            eina_matrix3_translate(&_matrix_tmp, -(Nd->x), -(Nd->y));   \
            eina_matrix3_compose(Parent, &_matrix_tmp, &_matrix_tmp);   \
            eina_matrix3_translate(&_matrix_tmp, (Nd->x), (Nd->y));     \
            Current = &_matrix_tmp;                                     \
         }                                                              \
    }


#endif