move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / xrender_x11 / evas_engine_xrender.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include "evas_common.h"
5 //#include "evas_macros.h"
6 #include "evas_private.h"
7 #include "evas_engine.h"
8 #include "Evas_Engine_XRender_X11.h"
9 #include <math.h>
10
11 /* this is a work around broken xrender - when/if this ever gets fixed in xorg
12  * we can comment this out and one day remove it - for now keep it until such
13  * a fix is spotted in the wild
14  */
15 #define BROKEN_XORG_XRENDER 1
16
17 /* should be const char*, but the prototype for XRenderSetPictureFilter
18  * is silly
19  */
20 static inline char *
21 get_filter(int smooth)
22 {
23    return smooth ? FilterBest : FilterNearest;
24 }
25
26 Xrender_Surface *
27 _xr_render_surface_new(Ximage_Info *xinf, int w, int h, XRenderPictFormat *fmt, int alpha)
28 {
29    Xrender_Surface *rs;
30    XRenderPictureAttributes att;
31    
32    if ((!xinf) || (!fmt) || (w < 1) || (h < 1)) return NULL;
33    rs = calloc(1, sizeof(Xrender_Surface));
34    if (!rs) return NULL;
35    rs->xinf = xinf;
36    rs->w = w;
37    rs->h = h;
38    rs->fmt = fmt;
39    rs->alpha = alpha;
40    rs->depth = fmt->depth;
41    rs->allocated = 1;
42    rs->draw = XCreatePixmap(xinf->disp, xinf->root, w, h, fmt->depth);
43    if (rs->draw == None)
44      {
45         free(rs);
46         return NULL;
47      }
48    rs->xinf->references++;
49    att.dither = 1;
50    att.component_alpha = 0;
51    att.repeat = 0;
52    rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt, 
53                                   CPRepeat | CPDither | CPComponentAlpha, &att);
54    if (rs->pic == None)
55      {
56         XFreePixmap(rs->xinf->disp, rs->draw);
57         rs->xinf->references--;
58         free(rs);
59         return NULL;
60      }
61    return rs;
62 }
63
64 Xrender_Surface *
65 _xr_render_surface_adopt(Ximage_Info *xinf, Drawable draw, int w, int h, int alpha)
66 {
67    Xrender_Surface *rs;
68    XRenderPictFormat *fmt;
69    XRenderPictureAttributes att;
70    
71    if ((!xinf) || (draw == None) || (w < 1) || (h < 1)) return NULL;
72    fmt = XRenderFindVisualFormat(xinf->disp, xinf->vis);
73    if (!fmt) return NULL;
74    rs = calloc(1, sizeof(Xrender_Surface));
75    if (!rs) return NULL;
76    rs->xinf = xinf;
77    rs->w = w;
78    rs->h = h;
79    rs->fmt = fmt;
80    rs->alpha = alpha;
81    rs->depth = fmt->depth;
82    if (fmt->depth == 32) rs->alpha = 1;
83    rs->allocated = 0;
84    rs->draw = draw;
85    rs->xinf->references++;
86    att.dither = 1;
87    att.component_alpha = 0;
88    att.repeat = 0;
89    rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt, 
90                                   CPRepeat | CPDither | CPComponentAlpha, &att);
91    if (rs->pic == None)
92      {
93         rs->xinf->references--;
94         free(rs);
95         return NULL;
96      }
97    return rs;
98 }
99
100 Xrender_Surface *
101 _xr_render_surface_format_adopt(Ximage_Info *xinf, Drawable draw, int w, int h, XRenderPictFormat *fmt, int alpha)
102 {
103    Xrender_Surface *rs;
104    XRenderPictureAttributes att;
105    
106    if ((!xinf) || (!fmt) || (draw == None) || (w < 1) || (h < 1)) return NULL;
107    rs = calloc(1, sizeof(Xrender_Surface));
108    if (!rs) return NULL;
109    rs->xinf = xinf;
110    rs->w = w;
111    rs->h = h;
112    rs->fmt = fmt;
113    rs->alpha = alpha;
114    rs->depth = fmt->depth;
115    if (fmt->depth == 32) rs->alpha = 1;
116    rs->xinf->references++;
117    rs->allocated = 0;
118    rs->draw = draw;
119    att.dither = 0;
120    att.component_alpha = 0;
121    att.repeat = 0;
122    rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt, CPRepeat | CPDither | CPComponentAlpha, &att);
123    if (rs->pic == None)
124      {
125         rs->xinf->references--;
126         free(rs);
127         return NULL;
128      }
129    return rs;
130 }
131
132 void
133 _xr_render_surface_free(Xrender_Surface *rs)
134 {
135    if (!rs) return;
136    if (rs->xinf)
137      {
138         if ((rs->allocated) && (rs->draw != None))
139            XFreePixmap(rs->xinf->disp, rs->draw);
140         if (rs->pic != None)
141            XRenderFreePicture(rs->xinf->disp, rs->pic);
142         _xr_image_info_free(rs->xinf);
143         rs->xinf = NULL;
144      }
145    free(rs);
146 }
147
148 void
149 _xr_render_surface_repeat_set(Xrender_Surface *rs, int repeat)
150 {
151    XRenderPictureAttributes att;
152    
153    att.repeat = repeat;
154    XRenderChangePicture(rs->xinf->disp, rs->pic, CPRepeat, &att);
155 }
156
157 void
158 _xr_render_surface_solid_rectangle_set(Xrender_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h)
159 {
160    XRenderColor col;
161    
162    col.red   = (r << 8) | r;
163    col.green = (g << 8) | g;
164    col.blue  = (b << 8) | b;
165    col.alpha = (a << 8) | a;
166    XRenderFillRectangle(rs->xinf->disp, PictOpSrc, rs->pic, &col, x, y, w, h);
167 }
168
169 void
170 _xr_render_surface_argb_pixels_fill(Xrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h, int ox, int oy)
171 {
172    Ximage_Image  *xim;
173    unsigned int  *p, *sp, *sple, *spe;
174    unsigned int   jump, sjump;
175    
176    xim = _xr_image_new(rs->xinf, w, h, rs->depth);
177    if (!xim) return;
178    p = (unsigned int *)xim->data;
179    sp = ((unsigned int *)pixels) + (y * sw) + x;
180    jump = ((xim->line_bytes / 4) - w);
181    sjump = sw - w;
182    spe = sp + ((h - 1) * sw) + w;
183    if
184 #ifdef WORDS_BIGENDIAN
185      (xim->xim->byte_order == LSBFirst)
186 #else
187      (xim->xim->byte_order == MSBFirst)
188 #endif
189      {
190         while (sp < spe)
191           {
192              sple = sp + w;
193              while (sp < sple)
194                {
195                   *p++ = (*sp << 24) + ((*sp << 8) & 0xff0000) + ((*sp >> 8) & 0xff00) + (*sp >> 24);
196 //                *p++ = (B_VAL(sp) << 24) | (G_VAL(sp) << 16) | (R_VAL(sp) << 8) | A_VAL(sp);
197                   sp++;
198                }
199              p += jump;
200              sp += sjump;
201           }
202      }
203    else
204      {
205         while (sp < spe)
206           {
207              sple = sp + w;
208              while (sp < sple)
209                 *p++ = *sp++;
210              p += jump;
211              sp += sjump;
212           }
213      }
214    _xr_image_put(xim, rs->draw, x + ox, y + oy, w, h);
215 }
216
217 void
218 _xr_render_surface_rgb_pixels_fill(Xrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h, int ox, int oy)
219 {
220    Ximage_Image  *xim;
221    unsigned int  *p, *sp, *sple, *spe;
222    unsigned int   jump, sjump;
223    
224    xim = _xr_image_new(rs->xinf, w, h, rs->depth);
225    if (!xim) return;
226    p = (unsigned int *)xim->data;
227    sp = ((unsigned int *)pixels) + (y * sw) + x;
228    sjump = sw - w;
229    spe = sp + ((h - 1) * sw) + w;
230    if (rs->depth == 16)
231      {
232         jump = ((xim->line_bytes / 2) - w);
233         /* FIXME: if rs->depth == 16 - convert */
234         Gfx_Func_Convert conv_func;
235         int swap;
236         
237 #ifdef WORDS_BIGENDIAN
238         swap = (int)(xim->xim->byte_order == LSBFirst);
239 #else
240         swap = (int)(xim->xim->byte_order == MSBFirst);
241 #endif
242         /* FIXME: swap not handled */
243         conv_func = evas_common_convert_func_get(sp, w, h, rs->depth,
244                                                  rs->xinf->vis->red_mask,
245                                                  rs->xinf->vis->green_mask,
246                                                  rs->xinf->vis->blue_mask,
247                                                  PAL_MODE_NONE, 0);
248         if (conv_func)
249           conv_func(sp, p, sjump, jump, w, h, x, y, NULL);
250      }
251    else
252      {
253         jump = ((xim->line_bytes / 4) - w);
254         if
255 #ifdef WORDS_BIGENDIAN
256           (xim->xim->byte_order == LSBFirst)
257 #else
258           (xim->xim->byte_order == MSBFirst)
259 #endif
260             {
261                while (sp < spe)
262                  {
263                     sple = sp + w;
264                     while (sp < sple)
265                       {
266                          *p++ = (*sp << 24) + ((*sp << 8) & 0xff0000) + ((*sp >> 8) & 0xff00) + 0xff;
267 //                *p++ = ((B_VAL(sp)) << 24) | ((G_VAL(sp)) << 16) | ((R_VAL(sp)) << 8) | 0x000000ff;
268                          sp++;
269                       }
270                     p += jump;
271                     sp += sjump;
272                  }
273             }
274         else
275           {
276              while (sp < spe)
277                {
278                   sple = sp + w;
279                   while (sp < sple)
280                     *p++ = 0xff000000 | *sp++;
281                   p += jump;
282                   sp += sjump;
283                }
284           }
285      }
286    _xr_image_put(xim, rs->draw, x + ox, y + oy, w, h);
287 }
288
289 void
290 _xr_render_surface_clips_set(Xrender_Surface *rs, RGBA_Draw_Context *dc, int rx, int ry, int rw, int rh)
291 {
292    int num = 0;
293    XRectangle *rect = NULL;
294    
295    if ((dc) && (dc->clip.use))
296      {
297         RECTS_CLIP_TO_RECT(rx, ry, rw, rh,
298                            dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
299      }
300    if ((!dc) || (!dc->cutout.rects))
301      {
302         rect = malloc(sizeof(XRectangle));
303         if (!rect) return;
304         rect->x = rx;
305         rect->y = ry;
306         rect->width = rw;
307         rect->height = rh;
308         num = 1;
309      }
310    else
311      {
312         Cutout_Rects    *rects;
313         Cutout_Rect     *r;
314         int i;
315
316         rects = evas_common_draw_context_apply_cutouts(dc);
317         num = rects->active;
318         rect = malloc(num * sizeof(XRectangle));
319         if (!rect) return;
320         for (i = 0; i < num; i++)
321           {
322              r = rects->rects + i;
323              rect[i].x = r->x;
324              rect[i].y = r->y;
325              rect[i].width = r->w;
326              rect[i].height = r->h;
327           }
328         evas_common_draw_context_apply_clear_cutouts(rects);
329      }
330    if (!rect) return;
331    XRenderSetPictureClipRectangles(rs->xinf->disp, rs->pic, 0, 0, rect, num);
332    free(rect);
333 }
334
335 /* initialized the transform to the identity */
336 static void
337 init_xtransform(XTransform *t)
338 {
339    int i, j;
340
341    for (i = 0; i < 3; i++)
342      for (j = 0; j < 3; j++)
343        t->matrix[i][j] = XDoubleToFixed((i == j) ? 1 : 0);
344 }
345
346 static void
347 set_xtransform_scale(XTransform *t, int sw, int sh, int w, int h, int tx, int ty)
348 {
349 //   if ((sw > 1) && (w > 1))
350 //     { sw--;  w--; }
351 //   if ((sh > 1) && (h > 1))
352 //     { sh--;  h--; }
353    t->matrix[0][0] = XDoubleToFixed((double)(sw) / (double)(w));
354    t->matrix[1][1] = XDoubleToFixed((double)(sh) / (double)(h));
355    t->matrix[2][0] = (tx * sw) / w;
356    t->matrix[2][1] = (ty * sh) / h;
357 }
358
359 // when color multiplier is used want: instead
360 // CA src IN mask SRC temp; non-CA temp OVER dst. - i think. need to check.
361 void
362 _xr_render_surface_composite(Xrender_Surface *srs, Xrender_Surface *drs, RGBA_Draw_Context *dc, int sx, int sy, int sw, int sh, int x, int y, int w, int h, int smooth)
363 {
364    Xrender_Surface *trs = NULL;
365    XTransform xf;
366    XRenderPictureAttributes att;
367    Picture mask = None;
368    int e, is_scaling, op;
369
370    if ((sw <= 0) || (sh <= 0) || (w <= 0) || (h <= 0)) return;
371    
372    is_scaling = e = ((sw != w) || (sh != h));
373
374    att.clip_mask = None;
375    XRenderChangePicture(srs->xinf->disp, srs->pic, CPClipMask, &att);
376    XRenderChangePicture(drs->xinf->disp, drs->pic, CPClipMask, &att);
377    
378    init_xtransform(&xf);
379
380    op = PictOpOver;
381    if (dc->render_op == _EVAS_RENDER_BLEND)
382      {
383         if (!srs->alpha) op = PictOpSrc;
384      }
385    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
386      op = PictOpAtop;
387    else if (dc->render_op == _EVAS_RENDER_MUL)
388      op = PictOpIn;
389    else if (dc->render_op == _EVAS_RENDER_COPY)
390      op = PictOpSrc;
391    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
392      op = PictOpIn;
393    else if (dc->render_op == _EVAS_RENDER_MASK)
394      op = PictOpInReverse;
395
396    if ((dc) && (dc->mul.use))
397      {
398         int r, g, b, a;
399
400         if ((op == PictOpOver) && (!dc->mul.col)) return;
401         a = dc->mul.col >> 24;
402         r = (dc->mul.col >> 16) & 0xff;
403         g = (dc->mul.col >> 8) & 0xff;
404         b = dc->mul.col & 0xff;
405         if (a < 255) op = PictOpOver;
406         if (dc->mul.col != 0xffffffff)
407           {
408              if ((srs->xinf->mul_r != r) || (srs->xinf->mul_g != g) ||
409                  (srs->xinf->mul_b != b) || (srs->xinf->mul_a != a))
410                {
411                   srs->xinf->mul_r = r;
412                   srs->xinf->mul_g = g;
413                   srs->xinf->mul_b = b;
414                   srs->xinf->mul_a = a;
415                   _xr_render_surface_solid_rectangle_set(srs->xinf->mul, 
416                                                          r, g, b, a, 
417                                                          0, 0, 1, 1);
418                }
419              mask = srs->xinf->mul->pic;
420              if (dc->mul.col == (a * 0x01010101))
421                {
422                  att.component_alpha = 0;
423                  XRenderChangePicture(srs->xinf->disp, mask, CPComponentAlpha, &att);
424                }
425              else
426                {
427                   if ((srs->alpha) || (a != 0xff))
428                     trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
429                                                  srs->xinf->fmt32, 1);
430                   else
431                     trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
432                                                  srs->fmt, srs->alpha);
433                   if (!trs) return;
434                   
435                   att.component_alpha = 1;
436                   XRenderChangePicture(srs->xinf->disp, mask, CPComponentAlpha, &att);
437                   XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
438                   XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, mask,
439                                    trs->pic, 
440                                    sx, sy, 
441                                    sx, sy, 
442                                    0, 0, sw + 2, sh + 2);
443                   mask = None;
444                }
445           }
446      }
447
448 //#define HFW + (sw / 2)
449 //#define HFH + (sh / 2)        
450 #define HFW
451 #define HFH
452    
453    _xr_render_surface_clips_set(drs, dc, x, y, w, h);
454    if (trs)
455      {
456         XRenderSetPictureFilter(trs->xinf->disp, trs->pic, get_filter(smooth), NULL, 0);
457
458         set_xtransform_scale(&xf, sw, sh, w, h, -1, -1);
459         XRenderSetPictureTransform(trs->xinf->disp, trs->pic, &xf);
460
461         att.component_alpha = 0;
462         if (dc->render_op == _EVAS_RENDER_MUL) att.component_alpha = 1;
463         XRenderChangePicture(trs->xinf->disp, trs->pic, CPComponentAlpha, &att);
464
465         XRenderComposite(trs->xinf->disp, op, trs->pic, mask, drs->pic,
466                          (w HFW) / sw, (h HFH) / sh,
467                          (w HFW) / sw, (h HFH) / sh,
468                          x, y, w, h);
469         _xr_render_surface_free(trs);
470      }
471    else
472      {
473         if (srs->bordered && is_scaling)
474           {
475              trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
476                                           srs->fmt, srs->alpha);
477              if (!trs) return;
478              
479              att.component_alpha = 0;
480              XRenderChangePicture(srs->xinf->disp, srs->pic, CPComponentAlpha, &att);
481              XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
482              
483              XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, None,
484                               trs->pic, sx, sy, sx, sy, 0, 0, sw + 2, sh + 2);
485              
486              XRenderSetPictureFilter(trs->xinf->disp, trs->pic, get_filter(smooth), NULL, 0);
487              
488              set_xtransform_scale(&xf, sw, sh, w, h, -1, -1);
489              XRenderSetPictureTransform(trs->xinf->disp, trs->pic, &xf);
490              
491              if (dc->render_op == _EVAS_RENDER_MUL)
492                {
493                   att.component_alpha = 1;
494                   XRenderChangePicture(trs->xinf->disp, trs->pic, CPComponentAlpha, &att);
495                }
496              
497              XRenderComposite(trs->xinf->disp, op, trs->pic, mask, drs->pic,
498                               (w HFW) / sw, (h HFH) / sh,
499                               (w HFW) / sw, (h HFH) / sh,
500 //                            1, 1, 1, 1,
501                               x, y, w, h);
502              _xr_render_surface_free(trs);
503           }
504         else
505           {
506              XRenderSetPictureFilter(srs->xinf->disp, srs->pic, get_filter(smooth), NULL, 0);
507              
508              set_xtransform_scale(&xf, sw, sh, w, h, 0, 0);
509              XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
510              
511              att.component_alpha = 0;
512              if (dc->render_op == _EVAS_RENDER_MUL)
513                att.component_alpha = 1;
514              XRenderChangePicture(srs->xinf->disp, srs->pic, CPComponentAlpha, &att);
515              
516              XRenderComposite(srs->xinf->disp, op, srs->pic, mask, drs->pic,
517                               ((((sx + 1) * w) HFW) / sw),
518                               ((((sy + 1) * h) HFH) / sh),
519                               ((((sx + 1) * w) HFW) / sw),
520                               ((((sy + 1) * h) HFH) / sh),
521                               x, y, w, h);
522           }
523      }
524 }
525
526 void
527 _xr_render_surface_copy(Xrender_Surface *srs, Xrender_Surface *drs, int sx, int sy, int x, int y, int w, int h)
528 {
529    XTransform xf;
530    XRenderPictureAttributes att;
531    
532    if ((w <= 0) || (h <= 0) || (!srs) || (!drs)) return;
533
534    init_xtransform(&xf);
535 #ifdef BROKEN_XORG_XRENDER   
536    /* FIXME: why do we need to change the identity matrix ifthe src surface
537     * is 1 bit deep?
538     */
539    if (srs->depth == 1)
540      {
541         xf.matrix[0][0] = xf.matrix[1][1] = xf.matrix[2][2] = 1;
542      }
543 #endif
544    XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
545 //   XRenderSetPictureFilter(srs->xinf->disp, srs->pic, FilterNearest, NULL, 0);
546    
547    att.clip_mask = None;
548    XRenderChangePicture(srs->xinf->disp, srs->pic, CPClipMask, &att);
549    XRenderChangePicture(drs->xinf->disp, drs->pic, CPClipMask, &att);
550    
551    XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, None, drs->pic, 
552                     sx, sy, 0, 0, x, y, w, h);
553 }
554
555 void
556 _xr_render_surface_rectangle_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, int x, int y, int w, int h)
557 {
558    XRenderColor col;
559    XRenderPictureAttributes att;
560    int r, g, b, a, op;
561
562    if ((!rs) || (!dc)) return;
563    if ((w <= 0) || (h <= 0)) return;
564    a = dc->col.col >> 24;
565    r = (dc->col.col >> 16) & 0xff;
566    g = (dc->col.col >> 8 ) & 0xff;
567    b = (dc->col.col      ) & 0xff;
568    col.red   = (r << 8) | r;
569    col.green = (g << 8) | g;
570    col.blue  = (b << 8) | b;
571    col.alpha = (a << 8) | a;
572    op = PictOpOver;
573    if (dc->render_op == _EVAS_RENDER_BLEND)
574      {
575         if (!dc->col.col) return;
576         if (a == 0xff) op = PictOpSrc;
577      }
578    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
579      {
580         if (!dc->col.col) return;
581         op = PictOpAtop;
582      }
583    else if (dc->render_op == _EVAS_RENDER_MUL)
584      {
585         if (dc->col.col == 0xffffffff) return;
586         op = PictOpIn;
587      }
588    else if (dc->render_op == _EVAS_RENDER_COPY)
589         op = PictOpSrc;
590    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
591         op = PictOpIn;
592    else if (dc->render_op == _EVAS_RENDER_MASK)
593         op = PictOpInReverse;
594
595    att.clip_mask = None;
596    XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
597
598    _xr_render_surface_clips_set(rs, dc, x, y, w, h);
599    XRenderFillRectangle(rs->xinf->disp, op, rs->pic, &col, x, y, w, h);
600 }
601
602 void
603 _xr_render_surface_line_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2)
604 {
605    XRenderPictureAttributes att;
606    int op;
607    
608    if ((!rs) || (!dc) || (!dc->col.col)) return;
609    op = PictOpOver;
610    if (dc->render_op == _EVAS_RENDER_BLEND)
611      {
612         if (!dc->col.col) return;
613      }
614    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
615      {
616         if (!dc->col.col) return;
617         op = PictOpAtop;
618      }
619    else if (dc->render_op == _EVAS_RENDER_MUL)
620      {
621         if (dc->col.col == 0xffffffff) return;
622         op = PictOpIn;
623      }
624    else if (dc->render_op == _EVAS_RENDER_COPY)
625         op = PictOpSrc;
626    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
627         op = PictOpIn;
628    else if (dc->render_op == _EVAS_RENDER_MASK)
629         op = PictOpInReverse;
630    att.clip_mask = None;
631    XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
632    _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h);
633
634      {
635         int r, g, b, a;
636         XPointDouble poly[4];
637         int dx, dy;
638         double len, ddx, ddy;
639         
640         dx = x2 - x1;
641         dy = y2 - y1;
642         len = sqrt((double)(dx * dx) + (double)(dy * dy));
643         ddx = (0.5 * dx) / len;
644         ddy = (0.5 * dy) / len;
645         if (ddx < 0) ddx = -0.5 - ddx;
646         else ddx = 0.5 - ddx;
647         if (ddy < 0) ddy = -0.5 - ddy;
648         else ddy = 0.5 - ddy;
649         poly[0].x =  (x1 + ddx);
650         poly[0].y =  (y1 - ddy);
651         poly[1].x =  (x2 + ddx);
652         poly[1].y =  (y2 - ddy);
653         poly[2].x =  (x2 - ddx);
654         poly[2].y =  (y2 + ddy);
655         poly[3].x =  (x1 - ddx);
656         poly[3].y =  (y1 + ddy);
657
658         a = (dc->col.col >> 24) & 0xff;
659         r = (dc->col.col >> 16) & 0xff;
660         g = (dc->col.col >> 8 ) & 0xff;
661         b = (dc->col.col      ) & 0xff;
662         if ((rs->xinf->mul_r != r) || (rs->xinf->mul_g != g) ||
663             (rs->xinf->mul_b != b) || (rs->xinf->mul_a != a))
664           {
665              rs->xinf->mul_r = r;
666              rs->xinf->mul_g = g;
667              rs->xinf->mul_b = b;
668              rs->xinf->mul_a = a;
669              _xr_render_surface_solid_rectangle_set(rs->xinf->mul, r, g, b, a, 0, 0, 1, 1);
670           }
671         XRenderCompositeDoublePoly(rs->xinf->disp, op,
672                                    rs->xinf->mul->pic, rs->pic, 
673                                    rs->xinf->fmt8, 0, 0, 0, 0,
674                                    poly, 4, EvenOddRule);
675      }
676 }
677
678 void
679 _xre_poly_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points)
680 {
681    RGBA_Polygon_Point *pt;
682    int i, num;
683    XPointDouble *pts;
684    int r, g, b, a;
685    XRenderPictureAttributes att;
686    int op;
687    
688    if ((!rs) || (!dc)) return;
689    num = 0;
690    for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) num++;
691    if (num < 3) return;
692    op = PictOpOver;
693    if (dc->render_op == _EVAS_RENDER_BLEND)
694      {
695         if (!dc->col.col) return;
696      }
697    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
698      {
699         if (!dc->col.col) return;
700         op = PictOpAtop;
701      }
702    else if (dc->render_op == _EVAS_RENDER_MUL)
703      {
704         if (dc->col.col == 0xffffffff) return;
705         op = PictOpIn;
706      }
707    else if (dc->render_op == _EVAS_RENDER_COPY)
708         op = PictOpSrc;
709    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
710         op = PictOpIn;
711    else if (dc->render_op == _EVAS_RENDER_MASK)
712         op = PictOpInReverse;
713    a = (dc->col.col >> 24) & 0xff;
714    r = (dc->col.col >> 16) & 0xff;
715    g = (dc->col.col >> 8 ) & 0xff;
716    b = (dc->col.col      ) & 0xff;
717    if ((rs->xinf->mul_r != r) || (rs->xinf->mul_g != g) ||
718        (rs->xinf->mul_b != b) || (rs->xinf->mul_a != a))
719      {
720         rs->xinf->mul_r = r;
721         rs->xinf->mul_g = g;
722         rs->xinf->mul_b = b;
723         rs->xinf->mul_a = a;
724         _xr_render_surface_solid_rectangle_set(rs->xinf->mul, r, g, b, a, 0, 0, 1, 1);
725      }
726    pts = malloc(num * sizeof(XPointDouble));
727    if (!pts) return;
728    i = 0;
729    for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next))
730      {
731         if (i < num)
732           {
733              pts[i].x = pt->x;
734              pts[i].y = pt->y;
735              i++;
736           }
737     }
738    att.clip_mask = None;
739    XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
740
741    _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h);
742    XRenderCompositeDoublePoly(rs->xinf->disp, op,
743                               rs->xinf->mul->pic, rs->pic, 
744                               rs->xinf->fmt8, 0, 0, 0, 0,
745                               pts, num, Complex);
746    free(pts);
747 }
748