summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_map_image_internal.c
blob: bc3a80912cae691a937fc233a35af4a2abd3e315 (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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// 66.74 % of time
static void
FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
          int clip_x, int clip_y, int clip_w, int clip_h,
          DATA32 mul_col, int render_op,
          RGBA_Map_Point *p,
          int smooth, int anti_alias, int level EINA_UNUSED, // level unused for now - for future use
          RGBA_Image *mask_ie, int mask_x, int mask_y)
{
   int i;
   int cx, cy, cw, ch;
   int ytop, ybottom, ystart, yend, y, sw, shp, swp, direct;
   Line *spans;
   DATA32 *buf = NULL, *sp;
   RGBA_Gfx_Func func = NULL, func2 = NULL;
   Eina_Bool havea = EINA_FALSE;
   Eina_Bool sa, ssa, da;
   int havecol = 4;

   cx = clip_x;
   cy = clip_y;
   cw = clip_w;
   ch = clip_h;

   // find y top line and collect point color info
   ytop = p[0].y;
   if ((p[0].col >> 24) < 0xff) havea = EINA_TRUE;
   if (p[0].col == 0xffffffff) havecol--;
   for (i = 1; i < 4; i++)
     {
        if (p[i].y < ytop) ytop = p[i].y;
        if ((p[i].col >> 24) < 0xff) havea = EINA_TRUE;
        if (p[i].col == 0xffffffff) havecol--;
     }

   // find y bottom line
   ybottom = p[0].y;
   for (i = 1; i < 4; i++)
     {
        if (p[i].y > ybottom) ybottom = p[i].y;
     }

   // convert to screen space from fixed point
   ytop = ytop >> FP;
   ybottom = ybottom >> FP;

   // if its outside the clip vertical bounds - don't bother
   if ((ytop >= (cy + ch)) || (ybottom < cy)) return;

   // limit to the clip vertical bounds
   if (ytop < cy) ystart = cy;
   else ystart = ytop;
   if (ybottom >= (cy + ch)) yend = (cy + ch) - 1;
   else yend = ybottom;

   // get some source image information
   sp = src->image.data;
   sw = src->cache_entry.w;
   swp = sw << (FP + FPI);
   shp = src->cache_entry.h << (FP + FPI);

   sa = src->cache_entry.flags.alpha;
   ssa = src->cache_entry.flags.alpha_sparse;
   da = dst->cache_entry.flags.alpha;

   // limit u,v coords of points to be within the source image
   for (i = 0; i < 4; i++)
     {
        if (p[i].u < 0) p[i].u = 0;
        else if (p[i].u > (int)(src->cache_entry.w << FP))
          p[i].u = src->cache_entry.w << FP;

        if (p[i].v < 0) p[i].v = 0;
        else if (p[i].v > (int)(src->cache_entry.h << FP))
          p[i].v = src->cache_entry.h << FP;
     }

   // allocate some spans to hold out span list
   spans = alloca((yend - ystart + 3) * sizeof(Line));
   memset(spans, 0, (yend - ystart + 3) * sizeof(Line));

   // calculate the spans list
   _calc_spans(p, spans, ystart, yend, cx, cy, cw, ch);

   // calculate anti alias edges
   if (anti_alias) _calc_aa_edges(spans, ystart, yend);

   // walk through spans and render

   // if operation is solid, bypass buf and draw func and draw direct to dst
   direct = 0;


   /* FIXME: even if anti-alias is enabled, only edges may require the
      pixels composition. we can optimize it. */

   if ((!sa) && (!da) &&
       (mul_col == 0xffffffff) && (!havea) && (!anti_alias) && (!mask_ie))
     {
        direct = 1;
     }
   else
     {
        buf = alloca(cw * sizeof(DATA32));
        if (havea) sa = 1;
        if (!mask_ie)
          {
             if (mul_col != 0xffffffff)
               func = evas_common_gfx_func_composite_pixel_color_span_get(sa, ssa, mul_col, da, cw, render_op);
             else
               func = evas_common_gfx_func_composite_pixel_span_get(sa, ssa, da, cw, render_op);
          }
        else
          {
             func = evas_common_gfx_func_composite_pixel_mask_span_get(sa, ssa, da, cw, render_op);
             if (mul_col != 0xffffffff)
               func2 = evas_common_gfx_func_composite_pixel_color_span_get(sa, ssa, mul_col, da, cw, EVAS_RENDER_COPY);
          }
        if (sa || anti_alias) src->cache_entry.flags.alpha = EINA_TRUE;
     }
   if (havecol == 0)
     {
#undef COLMUL
#include "evas_map_image_core.c"
     }
   else
     {
#define COLMUL 1
#include "evas_map_image_core.c"
     }
}

static void
FUNC_NAME_DO(RGBA_Image *src, RGBA_Image *dst,
             RGBA_Draw_Context *dc,
             const RGBA_Map_Spans *ms,
             int smooth, int anti_alias EINA_UNUSED, int level EINA_UNUSED) // level unused for now - for future use
{
   Line *spans;
   DATA32 *buf = NULL, *sp;
   RGBA_Gfx_Func func = NULL, func2 = NULL;
   int cx, cy, cw, ch;
   DATA32 mul_col;
   int ystart, yend, y, sw, shp, swp, direct;
   int havecol;
   int i;
   Eina_Bool sa, ssa, da;

   RGBA_Image *mask_ie = dc->clip.mask;
   int mask_x = dc->clip.mask_x;
   int mask_y = dc->clip.mask_y;

   cx = dc->clip.x;
   cy = dc->clip.y;
   cw = dc->clip.w;
   ch = dc->clip.h;

   mul_col = dc->mul.use ? dc->mul.col : 0xffffffff;

   if (ms->ystart < cy) ystart = cy;
   else ystart = ms->ystart;
   if (ms->yend >= (cy + ch)) yend = (cy + ch) - 1;
   else yend = ms->yend;

   // get some source image information
   sp = src->image.data;
   sw = src->cache_entry.w;
   swp = sw << (FP + FPI);
   shp = src->cache_entry.h << (FP + FPI);
   havecol = ms->havecol;
   direct = ms->direct;

   sa = src->cache_entry.flags.alpha;
   ssa = src->cache_entry.flags.alpha_sparse;
   da = dst->cache_entry.flags.alpha;

   // allocate some s to hold out span list
   spans = alloca((yend - ystart + 3) * sizeof(Line));
   memcpy(spans, &ms->spans[ystart - ms->ystart],
          (yend - ystart + 3) * sizeof(Line));
   _clip_spans(spans, ystart, yend, cx, cw, EINA_TRUE);

   // if operation is solid, bypass buf and draw func and draw direct to dst
   if (!direct)
     {
        buf = alloca(cw * sizeof(DATA32));
        if (ms->havea) sa = 1;
        if (!mask_ie)
          {
             if (mul_col != 0xffffffff)
               func = evas_common_gfx_func_composite_pixel_color_span_get(sa, ssa, dc->mul.col, da, cw, dc->render_op);
             else
               func = evas_common_gfx_func_composite_pixel_span_get(sa, ssa, da, cw, dc->render_op);
          }
        else
          {
             func = evas_common_gfx_func_composite_pixel_mask_span_get(sa, ssa, da, cw, dc->render_op);
             if (mul_col != 0xffffffff)
               func2 = evas_common_gfx_func_composite_pixel_color_span_get(sa, ssa, dc->mul.col, da, cw, EVAS_RENDER_COPY);
          }
        if (sa || anti_alias) src->cache_entry.flags.alpha = EINA_TRUE;
     }

   if (havecol == 0)
     {
#undef COLMUL
#include "evas_map_image_core.c"
     }
   else
     {
#define COLMUL 1
#include "evas_map_image_core.c"
     }
}