summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubhransu Mohanty <sub.mohanty@samsung.com>2015-08-17 14:26:40 +0900
committerCedric BAIL <cedric@osg.samsung.com>2015-08-19 15:02:53 +0200
commit8b075c65348e460166aa964c48f379938cd0bc7d (patch)
tree586566994b0fe8b870802847c5c70e2ed6bd80a7
parent230b75acab9665dd77445de6d303d7171d3f684b (diff)
ector: refactored shape generation in software backend.
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/lib/ector/software/ector_renderer_software_shape.c284
1 files changed, 178 insertions, 106 deletions
diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c
index 1c985d4518..2ea12eeebe 100644
--- a/src/lib/ector/software/ector_renderer_software_shape.c
+++ b/src/lib/ector/software/ector_renderer_software_shape.c
@@ -30,18 +30,38 @@ typedef struct _Outline
30 int contours_alloc; 30 int contours_alloc;
31}Outline; 31}Outline;
32 32
33
34static inline void
35_grow_outline_contour(Outline *outline, int num)
36{
37 if ( outline->ft_outline.n_contours + num > outline->contours_alloc)
38 {
39 outline->contours_alloc += 5;
40 outline->ft_outline.contours = (short *) realloc(outline->ft_outline.contours,
41 outline->contours_alloc * sizeof(short));
42 }
43}
44
45static inline void
46_grow_outline_points(Outline *outline, int num)
47{
48 if ( outline->ft_outline.n_points + num > outline->points_alloc)
49 {
50 outline->points_alloc += 50;
51 outline->ft_outline.points = (SW_FT_Vector *) realloc(outline->ft_outline.points,
52 outline->points_alloc * sizeof(SW_FT_Vector));
53 outline->ft_outline.tags = (char *) realloc(outline->ft_outline.tags,
54 outline->points_alloc * sizeof(char));
55 }
56}
33static Outline * 57static Outline *
34_outline_create() 58_outline_create()
35{ 59{
36 Outline *outline = (Outline *) calloc(1, sizeof(Outline)); 60 Outline *outline = (Outline *) calloc(1, sizeof(Outline));
37 61 outline->points_alloc = 0;
38 outline->ft_outline.points = (SW_FT_Vector *) calloc(50, sizeof(SW_FT_Vector)); 62 outline->contours_alloc = 0;
39 outline->ft_outline.tags = (char *) calloc(50, sizeof(char)); 63 _grow_outline_contour(outline, 1);
40 64 _grow_outline_points(outline, 1);
41 outline->ft_outline.contours = (short *) calloc(5, sizeof(short));
42
43 outline->points_alloc = 50;
44 outline->contours_alloc = 5;
45 return outline; 65 return outline;
46} 66}
47 67
@@ -63,17 +83,14 @@ _outline_move_to(Outline *outline, double x, double y)
63{ 83{
64 SW_FT_Outline *ft_outline = &outline->ft_outline; 84 SW_FT_Outline *ft_outline = &outline->ft_outline;
65 85
66 if (ft_outline->n_contours == outline->contours_alloc) 86 _grow_outline_points(outline, 1);
67 {
68 outline->contours_alloc += 5;
69 ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
70 }
71 ft_outline->points[ft_outline->n_points].x = x; 87 ft_outline->points[ft_outline->n_points].x = x;
72 ft_outline->points[ft_outline->n_points].y = y; 88 ft_outline->points[ft_outline->n_points].y = y;
73 ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON; 89 ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
74 90
75 if (ft_outline->n_points) 91 if (ft_outline->n_points)
76 { 92 {
93 _grow_outline_contour(outline, 1);
77 ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1; 94 ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
78 ft_outline->n_contours++; 95 ft_outline->n_contours++;
79 } 96 }
@@ -86,11 +103,7 @@ _outline_end(Outline *outline)
86{ 103{
87 SW_FT_Outline *ft_outline = &outline->ft_outline; 104 SW_FT_Outline *ft_outline = &outline->ft_outline;
88 105
89 if (ft_outline->n_contours == outline->contours_alloc) 106 _grow_outline_contour(outline, 1);
90 {
91 outline->contours_alloc += 1;
92 ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
93 }
94 107
95 if (ft_outline->n_points) 108 if (ft_outline->n_points)
96 { 109 {
@@ -104,12 +117,7 @@ static void _outline_line_to(Outline *outline, double x, double y)
104{ 117{
105 SW_FT_Outline *ft_outline = &outline->ft_outline; 118 SW_FT_Outline *ft_outline = &outline->ft_outline;
106 119
107 if (ft_outline->n_points == outline->points_alloc) 120 _grow_outline_points(outline, 1);
108 {
109 outline->points_alloc += 50;
110 ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
111 ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
112 }
113 ft_outline->points[ft_outline->n_points].x = x; 121 ft_outline->points[ft_outline->n_points].x = x;
114 ft_outline->points[ft_outline->n_points].y = y; 122 ft_outline->points[ft_outline->n_points].y = y;
115 ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON; 123 ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
@@ -141,16 +149,12 @@ _outline_close_path(Outline *outline)
141} 149}
142 150
143 151
144static void _outline_cubic_to(Outline *outline, double cx1, double cy1, double cx2, double cy2, double x, double y) 152static void _outline_cubic_to(Outline *outline, double cx1, double cy1,
153 double cx2, double cy2, double x, double y)
145{ 154{
146 SW_FT_Outline *ft_outline = &outline->ft_outline; 155 SW_FT_Outline *ft_outline = &outline->ft_outline;
147 156
148 if (ft_outline->n_points == outline->points_alloc) 157 _grow_outline_points(outline, 3);
149 {
150 outline->points_alloc += 50;
151 ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
152 ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
153 }
154 158
155 ft_outline->points[ft_outline->n_points].x = cx1; 159 ft_outline->points[ft_outline->n_points].x = cx1;
156 ft_outline->points[ft_outline->n_points].y = cy1; 160 ft_outline->points[ft_outline->n_points].y = cy1;
@@ -171,14 +175,17 @@ static void _outline_cubic_to(Outline *outline, double cx1, double cy1, double
171static void _outline_transform(Outline *outline, Eina_Matrix3 *m) 175static void _outline_transform(Outline *outline, Eina_Matrix3 *m)
172{ 176{
173 int i; 177 int i;
178 double x, y;
174 SW_FT_Outline *ft_outline = &outline->ft_outline; 179 SW_FT_Outline *ft_outline = &outline->ft_outline;
175 180
176 if (m) 181 if (m)
177 { 182 {
178 double x, y;
179 for (i = 0; i < ft_outline->n_points; i++) 183 for (i = 0; i < ft_outline->n_points; i++)
180 { 184 {
181 eina_matrix3_point_transform(m, ft_outline->points[i].x, ft_outline->points[i].y, &x, &y); 185 eina_matrix3_point_transform(m,
186 ft_outline->points[i].x,
187 ft_outline->points[i].y,
188 &x, &y);
182 ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate. 189 ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate.
183 ft_outline->points[i].y = (int)(y * 64); 190 ft_outline->points[i].y = (int)(y * 64);
184 } 191 }
@@ -193,98 +200,145 @@ static void _outline_transform(Outline *outline, Eina_Matrix3 *m)
193 } 200 }
194} 201}
195 202
196
197static Eina_Bool 203static Eina_Bool
198_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Shape_Data *pd) 204_generate_outline(const Efl_Gfx_Path_Command *cmds, const double *pts, Outline * outline)
199{ 205{
200 const Efl_Gfx_Path_Command *cmds = NULL; 206 Eina_Bool close_path = EINA_FALSE;
201 const double *pts = NULL; 207 for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
208 {
209 switch (*cmds)
210 {
211 case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
202 212
203 // FIXME: shouldn't that be part of the shape generic implementation ? 213 _outline_move_to(outline, pts[0], pts[1]);
204 if (pd->shape->fill)
205 eo_do(pd->shape->fill, ector_renderer_prepare());
206 if (pd->shape->stroke.fill)
207 eo_do(pd->shape->stroke.fill, ector_renderer_prepare());
208 if (pd->shape->stroke.marker)
209 eo_do(pd->shape->stroke.marker, ector_renderer_prepare());
210 214
211 // shouldn't that be moved to the software base object 215 pts += 2;
212 if (!pd->surface) 216 break;
213 { 217 case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
214 Eo *parent;
215 eo_do(obj, parent = eo_parent_get());
216 if (!parent) return EINA_FALSE;
217 pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
218 if (!pd->surface) return EINA_FALSE;
219 }
220 218
221 eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts)); 219 _outline_line_to(outline, pts[0], pts[1]);
222 if (!pd->shape_data && cmds)
223 {
224 Eina_Bool close_path = EINA_FALSE;
225 Outline * outline = _outline_create();
226 220
227 for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++) 221 pts += 2;
228 { 222 break;
229 switch (*cmds) 223 case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
230 {
231 case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
232 224
233 _outline_move_to(outline, pts[0], pts[1]); 225 // Be careful, we do have a different order than
226 // cairo, first is destination point, followed by
227 // the control point. The opposite of cairo.
228 _outline_cubic_to(outline,
229 pts[2], pts[3], pts[4], pts[5], // control points
230 pts[0], pts[1]); // destination point
231 pts += 6;
232 break;
234 233
235 pts += 2; 234 case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
236 break;
237 case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
238 235
239 _outline_line_to(outline, pts[0], pts[1]); 236 close_path = _outline_close_path(outline);
237 break;
240 238
241 pts += 2; 239 case EFL_GFX_PATH_COMMAND_TYPE_LAST:
242 break; 240 case EFL_GFX_PATH_COMMAND_TYPE_END:
243 case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO: 241 break;
242 }
243 }
244 _outline_end(outline);
245 return close_path;
246}
244 247
245 // Be careful, we do have a different order than 248static Eina_Bool
246 // cairo, first is destination point, followed by 249_generate_stroke_data(Ector_Renderer_Software_Shape_Data *pd)
247 // the control point. The opposite of cairo. 250{
248 _outline_cubic_to(outline, 251 if (pd->outline_data) return EINA_FALSE;
249 pts[2], pts[3], pts[4], pts[5], // control points
250 pts[0], pts[1]); // destination point
251 pts += 6;
252 break;
253 252
254 case EFL_GFX_PATH_COMMAND_TYPE_CLOSE: 253 if (!pd->shape->stroke.fill &&
254 ((pd->shape->stroke.color.a == 0) ||
255 (pd->shape->stroke.width < 0.01)))
256 return EINA_FALSE;
255 257
256 close_path = _outline_close_path(outline); 258 return EINA_TRUE;
257 break; 259}
258 260
259 case EFL_GFX_PATH_COMMAND_TYPE_LAST: 261static Eina_Bool
260 case EFL_GFX_PATH_COMMAND_TYPE_END: 262_generate_shape_data(Ector_Renderer_Software_Shape_Data *pd)
261 break; 263{
262 } 264 if (pd->shape_data) return EINA_FALSE;
263 } 265
266 if (!pd->shape->fill && (pd->base->color.a == 0)) return EINA_FALSE;
267
268 return EINA_TRUE;
269}
270
271static void
272_update_rle(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
273{
274 const Efl_Gfx_Path_Command *cmds = NULL;
275 const double *pts = NULL;
276 Eina_Bool close_path;
277 Outline *outline, *dash_outline;
264 278
265 _outline_end(outline); 279 eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
280 if (cmds && (_generate_stroke_data(pd) || _generate_shape_data(pd)))
281 {
282 outline = _outline_create();
283 close_path = _generate_outline(cmds, pts, outline);
266 _outline_transform(outline, pd->base->m); 284 _outline_transform(outline, pd->base->m);
267 285
268 // generate the shape data. 286 //shape data generation
269 pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, &outline->ft_outline); 287 if (_generate_shape_data(pd))
270 if (!pd->outline_data) 288 pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software,
289 &outline->ft_outline);
290
291 //stroke data generation
292 if ( _generate_stroke_data(pd))
271 { 293 {
272 ector_software_rasterizer_stroke_set(pd->surface->software, (pd->shape->stroke.width * pd->shape->stroke.scale), pd->shape->stroke.cap, 294 ector_software_rasterizer_stroke_set(pd->surface->software,
295 (pd->shape->stroke.width *
296 pd->shape->stroke.scale),
297 pd->shape->stroke.cap,
273 pd->shape->stroke.join); 298 pd->shape->stroke.join);
274 pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software, &outline->ft_outline, close_path); 299 pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software,
300 &outline->ft_outline,
301 close_path);
275 } 302 }
276
277 _outline_destroy(outline); 303 _outline_destroy(outline);
278 } 304 }
305}
306
307static Eina_Bool
308_ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj,
309 Ector_Renderer_Software_Shape_Data *pd)
310{
311 // FIXME: shouldn't that be part of the shape generic implementation ?
312 if (pd->shape->fill)
313 eo_do(pd->shape->fill, ector_renderer_prepare());
314 if (pd->shape->stroke.fill)
315 eo_do(pd->shape->stroke.fill, ector_renderer_prepare());
316 if (pd->shape->stroke.marker)
317 eo_do(pd->shape->stroke.marker, ector_renderer_prepare());
279 318
319 // shouldn't that be moved to the software base object
320 if (!pd->surface)
321 {
322 Eo *parent;
323 eo_do(obj, parent = eo_parent_get());
324 if (!parent) return EINA_FALSE;
325 pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
326 if (!pd->surface) return EINA_FALSE;
327 }
280 return EINA_TRUE; 328 return EINA_TRUE;
281} 329}
282 330
283static Eina_Bool 331static Eina_Bool
284_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, unsigned int mul_col) 332_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj,
333 Ector_Renderer_Software_Shape_Data *pd,
334 Ector_Rop op, Eina_Array *clips,
335 unsigned int mul_col)
285{ 336{
286 int x, y; 337 int x, y;
287 338
339 // do lazy creation of rle
340 _update_rle(obj, pd);
341
288 // adjust the offset 342 // adjust the offset
289 x = pd->surface->x + (int)pd->base->origin.x; 343 x = pd->surface->x + (int)pd->base->origin.x;
290 y = pd->surface->y + (int)pd->base->origin.y; 344 y = pd->surface->y + (int)pd->base->origin.y;
@@ -296,30 +350,44 @@ _ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNU
296 if (pd->shape->fill) 350 if (pd->shape->fill)
297 { 351 {
298 eo_do(pd->shape->fill, ector_renderer_software_base_fill()); 352 eo_do(pd->shape->fill, ector_renderer_software_base_fill());
299 ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data); 353 ector_software_rasterizer_draw_rle_data(pd->surface->software,
354 x, y, mul_col, op,
355 pd->shape_data);
300 } 356 }
301 else 357 else
302 { 358 {
303 if (pd->base->color.a > 0) 359 if (pd->base->color.a > 0)
304 { 360 {
305 ector_software_rasterizer_color_set(pd->surface->software, pd->base->color.r, pd->base->color.g, pd->base->color.b, pd->base->color.a); 361 ector_software_rasterizer_color_set(pd->surface->software,
306 ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data); 362 pd->base->color.r,
363 pd->base->color.g,
364 pd->base->color.b,
365 pd->base->color.a);
366 ector_software_rasterizer_draw_rle_data(pd->surface->software,
367 x, y, mul_col, op,
368 pd->shape_data);
307 } 369 }
308 } 370 }
309 371
310 if (pd->shape->stroke.fill) 372 if (pd->shape->stroke.fill)
311 { 373 {
312 eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill()); 374 eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill());
313 ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data); 375 ector_software_rasterizer_draw_rle_data(pd->surface->software,
376 x, y, mul_col, op,
377 pd->outline_data);
314 } 378 }
315 else 379 else
316 { 380 {
317 if (pd->shape->stroke.color.a > 0) 381 if (pd->shape->stroke.color.a > 0)
318 { 382 {
319 ector_software_rasterizer_color_set(pd->surface->software, 383 ector_software_rasterizer_color_set(pd->surface->software,
320 pd->shape->stroke.color.r, pd->shape->stroke.color.g, 384 pd->shape->stroke.color.r,
321 pd->shape->stroke.color.b, pd->shape->stroke.color.a); 385 pd->shape->stroke.color.g,
322 ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data); 386 pd->shape->stroke.color.b,
387 pd->shape->stroke.color.a);
388 ector_software_rasterizer_draw_rle_data(pd->surface->software,
389 x, y, mul_col, op,
390 pd->outline_data);
323 } 391 }
324 } 392 }
325 393
@@ -327,7 +395,8 @@ _ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNU
327} 395}
328 396
329static Eina_Bool 397static Eina_Bool
330_ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd EINA_UNUSED) 398_ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED,
399 Ector_Renderer_Software_Shape_Data *pd EINA_UNUSED)
331{ 400{
332 // FIXME: let's find out how to fill a shape with a shape later. 401 // FIXME: let's find out how to fill a shape with a shape later.
333 // I need to read SVG specification and see how to map that with software. 402 // I need to read SVG specification and see how to map that with software.
@@ -335,8 +404,10 @@ _ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UN
335} 404}
336 405
337static void 406static void
338_ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_Software_Shape_Data *pd, 407_ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj,
339 const Efl_Gfx_Path_Command *op, const double *points) 408 Ector_Renderer_Software_Shape_Data *pd,
409 const Efl_Gfx_Path_Command *op,
410 const double *points)
340{ 411{
341 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data); 412 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
342 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data); 413 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
@@ -348,7 +419,8 @@ _ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_So
348 419
349 420
350static Eina_Bool 421static Eina_Bool
351_ector_renderer_software_shape_path_changed(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, 422_ector_renderer_software_shape_path_changed(void *data, Eo *obj EINA_UNUSED,
423 const Eo_Event_Description *desc EINA_UNUSED,
352 void *event_info EINA_UNUSED) 424 void *event_info EINA_UNUSED)
353{ 425{
354 Ector_Renderer_Software_Shape_Data *pd = data; 426 Ector_Renderer_Software_Shape_Data *pd = data;