move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_gradient_linear.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include <math.h>
6
7 #include "evas_common.h"
8 #include "evas_gradient_private.h"
9
10 #define GRAD_LINEAR_DIAG 1
11 #define GRAD_LINEAR_CODIAG 2
12
13 typedef struct _Linear_Data   Linear_Data;
14 struct _Linear_Data
15 {
16    int    type;
17
18    int    yy0;
19    float  ca, sa;
20    float  off;
21    int    len;
22
23    unsigned char at_angle : 1;
24 };
25
26 static void
27 linear_init(void);
28
29 static void
30 linear_shutdown(void);
31
32 static void
33 linear_init_geom(RGBA_Gradient *gr);
34
35 static void
36 linear_setup_geom(RGBA_Gradient *gr);
37
38 static void
39 linear_free_geom(void *gdata);
40
41 static int
42 linear_has_alpha(RGBA_Gradient *gr, int op);
43
44 static int
45 linear_has_mask(RGBA_Gradient *gr, int op);
46
47 static int
48 linear_get_map_len(RGBA_Gradient *gr);
49
50 static Gfx_Func_Gradient_Fill
51 linear_get_fill_func(RGBA_Gradient *gr, int op, unsigned char aa);
52
53 static RGBA_Gradient_Type  linear = {"linear", linear_init, linear_shutdown,
54                                      linear_init_geom, linear_setup_geom, linear_free_geom,
55                                      linear_has_alpha, linear_has_mask,
56                                      linear_get_map_len, linear_get_fill_func};
57
58
59
60 /** internal functions **/
61 static void
62 linear_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
63                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
64
65 static void
66 linear_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
67                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
68
69 static void
70 linear_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
71               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
72
73 static void
74 linear_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
75                  int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
76
77 static void
78 linear_restrict(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
79                 int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
80
81 static void
82 linear_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
83                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
84
85 static void
86 linear_restrict_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
87                        int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
88
89 static void
90 linear_restrict_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
91                           int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
92
93 static void
94 linear_restrict_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
95                         int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
96
97 static void
98 linear_restrict_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
99                            int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
100
101 static void
102 linear_restrict_reflect_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
103                                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
104
105 static void
106 linear_restrict_reflect_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
107                                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
108
109 static void
110 linear_restrict_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
111                        int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
112
113 static void
114 linear_restrict_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
115                           int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
116
117 static void
118 linear_restrict_repeat_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
119                               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
120
121 static void
122 linear_restrict_repeat_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
123                                  int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
124
125 static void
126 linear_pad(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
127            int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
128
129 static void
130 linear_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
131               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
132
133
134
135 RGBA_Gradient_Type  *
136 evas_common_gradient_linear_get(void)
137 {
138     return &linear;
139 }
140
141 static void
142 linear_init(void)
143 {
144 }
145
146 static void
147 linear_shutdown(void)
148 {
149 }
150
151 static void
152 linear_free_geom(void *gdata)
153 {
154    Linear_Data *data = (Linear_Data *)gdata;
155    if (data) free(data);
156 }
157
158 static void
159 linear_init_geom(RGBA_Gradient *gr)
160 {
161    Linear_Data *linear_data;
162
163    if (!gr || (gr->type.geometer != &linear)) return;
164    linear_data = (Linear_Data *)gr->type.gdata;
165    if (!linear_data)
166      {
167         linear_data = calloc(1, sizeof(Linear_Data));
168         if (!linear_data)  return;
169         linear_data->type = 0;
170         linear_data->yy0 = 0;
171         linear_data->ca = 1.0;
172         linear_data->sa = 0.0;
173         linear_data->off = 0.0;
174         linear_data->len = 32;
175         linear_data->at_angle = 0;
176         gr->type.gdata = linear_data;
177      }
178
179    linear_data->type = 0;
180    if (gr->type.name && !strcmp(gr->type.name, "linear.diag"))
181         linear_data->type = GRAD_LINEAR_DIAG;
182    else if (gr->type.name && !strcmp(gr->type.name, "linear.codiag"))
183         linear_data->type = GRAD_LINEAR_CODIAG;
184 }
185
186 static void
187 linear_setup_geom(RGBA_Gradient *gr)
188 {
189    Linear_Data *linear_data;
190    float  angle, a, ca, sa;
191    int    xoff = 0, yoff = 0;
192
193    if (!gr || (gr->type.geometer != &linear)) return;
194    linear_data = (Linear_Data *)gr->type.gdata;
195    if (!linear_data) return;
196
197    angle = gr->map.angle;
198    if (linear_data->type == GRAD_LINEAR_DIAG)
199         angle += ((atan2(gr->fill.h - 1, gr->fill.w - 1) * 180.0) / M_PI) - 90.0;
200    else if (linear_data->type == GRAD_LINEAR_CODIAG)
201         angle -= ((atan2(gr->fill.h - 1, gr->fill.w - 1) * 180.0) / M_PI) - 90.0;
202    a = ((angle + 90.0) * M_PI) / 180.0;
203    ca = cos(a);
204    sa = sin(a);
205    if ((sa >= 0) && (ca <= 0))
206      {
207         ca = -ca;
208         xoff = -(gr->fill.w - 1);
209      }
210    else if ((sa <= 0) && (ca <= 0))
211      {
212         ca = -ca;  sa = -sa;
213         xoff = -(gr->fill.w - 1);
214         yoff = -(gr->fill.h - 1);
215      }
216    else if ((sa <= 0) && (ca >= 0))
217      {
218         sa = -sa;
219         yoff = -(gr->fill.h - 1);
220      }
221    linear_data->len = 0.9961 + (ca * gr->fill.w) + (sa * gr->fill.h);
222
223    a = (angle * M_PI) / 180.0;
224    linear_data->ca = cos(a);
225    linear_data->sa = sin(a);
226
227    linear_data->yy0 = (linear_data->ca * (yoff << 16)) - (linear_data->sa * (xoff << 16));
228    linear_data->off = gr->map.offset;
229
230    if ((linear_data->ca != 1.0) || (linear_data->sa != 0.0))
231         linear_data->at_angle = 1;
232 }
233
234 static int
235 linear_has_alpha(RGBA_Gradient *gr, int op)
236 {
237    if (!gr || (gr->type.geometer != &linear)) return 0;
238    if (gr->has_alpha | gr->map.has_alpha)
239         return 1;
240    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
241          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
242         return 0;
243    if ( (gr->fill.spread == _EVAS_TEXTURE_RESTRICT) ||
244          (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REFLECT) ||
245          (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REPEAT) )
246         return 1;
247    return 0;
248 }
249
250 static int
251 linear_has_mask(RGBA_Gradient *gr, int op)
252 {
253    if (!gr || (gr->type.geometer != &linear)) return 0;
254    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
255          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
256      {
257         if ( (gr->fill.spread == _EVAS_TEXTURE_RESTRICT) ||
258               (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REFLECT) ||
259               (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REPEAT) )
260             return 1;
261      }
262    return 0;
263 }
264
265 static int
266 linear_get_map_len(RGBA_Gradient *gr)
267 {
268    Linear_Data   *linear_data;
269
270    if (!gr || (gr->type.geometer != &linear)) return 0;
271    linear_data = (Linear_Data *)gr->type.gdata;
272    if (!linear_data) return 0;
273    return linear_data->len;
274 }
275
276 static Gfx_Func_Gradient_Fill
277 linear_get_fill_func(RGBA_Gradient *gr, int op, unsigned char aa)
278 {
279    Linear_Data   *linear_data;
280    Gfx_Func_Gradient_Fill  sfunc = NULL;
281    int masked_op = 0;
282
283    if (!gr || (gr->type.geometer != &linear))
284         return sfunc;
285    linear_data = (Linear_Data *)gr->type.gdata;
286    if (!linear_data) return sfunc;
287
288    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
289          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
290         masked_op = 1;
291
292    switch (gr->fill.spread)
293      {
294       case _EVAS_TEXTURE_REFLECT:
295         {
296          if (aa)
297                sfunc = linear_reflect_aa;
298          else
299                sfunc = linear_reflect;
300         }
301       break;
302       case _EVAS_TEXTURE_REPEAT:
303         {
304          if (aa)
305             sfunc = linear_repeat_aa;
306          else
307             sfunc = linear_repeat;
308         }
309       break;
310       case _EVAS_TEXTURE_RESTRICT:
311         {
312          if (aa)
313            {
314              if (masked_op)
315                 sfunc = linear_restrict_aa_masked;
316              else
317                 sfunc = linear_restrict_aa;
318            }
319          else
320            {
321              if (masked_op)
322                 sfunc = linear_restrict_masked;
323              else
324                 sfunc = linear_restrict;
325            }
326         }
327       break;
328       case _EVAS_TEXTURE_RESTRICT_REFLECT:
329         {
330          if (aa)
331            {
332              if (masked_op)
333                 sfunc = linear_restrict_reflect_aa_masked;
334              else
335                 sfunc = linear_restrict_reflect_aa;
336            }
337          else
338            {
339              if (masked_op)
340                 sfunc = linear_restrict_reflect_masked;
341              else
342                 sfunc = linear_restrict_reflect;
343            }
344         }
345       break;
346       case _EVAS_TEXTURE_RESTRICT_REPEAT:
347         {
348          if (aa)
349            {
350              if (masked_op)
351                 sfunc = linear_restrict_repeat_aa_masked;
352              else
353                 sfunc = linear_restrict_repeat_aa;
354            }
355          else
356            {
357              if (masked_op)
358                 sfunc = linear_restrict_repeat_masked;
359              else
360                 sfunc = linear_restrict_repeat;
361            }
362         }
363       break;
364       case _EVAS_TEXTURE_PAD:
365         {
366          if (aa)
367                sfunc = linear_pad_aa;
368          else
369                sfunc = linear_pad;
370         }
371       break;
372       default:
373         sfunc = linear_reflect_aa;
374       break;
375      }
376    return sfunc;
377 }
378
379 /* the fill functions */
380
381 #ifdef BUILD_MMX
382 #define INTERP_256_P2R(a, s, mma, mms, mmd, mmz) \
383             MOV_A2R(a, mma) \
384             MOV_P2R(s, mms, mmz) \
385             INTERP_256_R2R(mma, mms, mmd, mm5)
386
387 #define MUL_256_A2R(a, mma, mmd, mmz) \
388         MOV_A2R(a, mma) \
389         MUL4_256_R2R(mma, mmd)
390 #endif
391
392 #define AXIS_ALIGNED \
393    ( ((ayy == 0) || (ayx == 0)) && ((gdata->ca == 0.0) || (gdata->sa == 0.0)) )
394
395 #define SETUP_LINEAR_FILL \
396    if (gdata->at_angle) \
397      { \
398         ayx = (-gdata->sa * axx) + (gdata->ca * ayx); \
399         ayy = (-gdata->sa * axy) + (gdata->ca * ayy); \
400      } \
401    yy = (ayx * x) + (ayy * y) + gdata->yy0;
402
403
404 static void
405 linear_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
406                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
407 {
408    DATA32  *dst_end = dst + dst_len;
409    Linear_Data  *gdata = (Linear_Data *)params_data;
410    int      off = gdata->off * (src_len - 1);
411    int      yy;
412
413    SETUP_LINEAR_FILL
414
415    if (ayx == 0)
416      {
417         DATA32  c;
418
419         y = (yy >> 16) + off;
420         if (y < 0)  y = -y;
421         if (y >= src_len)
422           {
423             int  m = (y % (2 * src_len));
424
425             y = (y % src_len);
426             if (m >= src_len)
427                 y = src_len - y - 1;
428           }
429         c = src[y];
430         while (dst < dst_end)
431             *dst++ = c;
432         return;
433      }
434
435    while (dst < dst_end)
436      {
437         int  l = (yy >> 16);
438
439         l += ((yy - (l << 16)) >> 15) + off;
440         if (l < 0)  l = -l;
441         if (l >= src_len)
442           {
443             int  m = (l % (2 * src_len));
444
445             l = (l % src_len);
446             if (m >= src_len)
447                 l = src_len - l - 1;
448           }
449         *dst++ = src[l];  yy += ayx;
450      }
451 }
452
453 static void
454 linear_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
455                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
456 {
457    DATA32  *dst_end = dst + dst_len;
458    Linear_Data  *gdata = (Linear_Data *)params_data;
459    int      off = gdata->off * (src_len - 1);
460    int      yy;
461
462    if (AXIS_ALIGNED)
463      {
464         linear_reflect(src, src_len, dst, mask, dst_len, x, y,
465                        axx, axy, ayx, ayy, params_data);
466         return;
467      }
468
469    SETUP_LINEAR_FILL
470
471 #ifdef BUILD_MMX
472    pxor_r2r(mm0, mm0);
473    MOV_A2R(ALPHA_255, mm5)
474 #endif
475    while (dst < dst_end)
476      {
477         int  l = (yy >> 16);
478         int  a = 1 + ((yy - (l << 16)) >> 8);
479
480         l += off;
481         if (l < 0) { l = -l;  a = 257 - a; }
482         if (l >= src_len)
483           {
484             int  m = (l % (2 * src_len));
485
486             l = (l % src_len);
487             if (m >= src_len)
488               { l = src_len - l - 1;  a = 257 - a; }
489           }
490 #ifdef BUILD_MMX
491         MOV_P2R(src[l], mm1, mm0)
492 #else
493         *dst = src[l];
494 #endif
495         if (l + 1 < src_len)
496           {
497 #ifdef BUILD_MMX
498             INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
499 #else
500             *dst = INTERP_256(a, src[l + 1], *dst);
501 #endif
502           }
503 #ifdef BUILD_MMX
504         MOV_R2P(mm1, *dst, mm0)
505 #endif
506         dst++;  yy += ayx;
507      }
508 }
509
510 static void
511 linear_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
512               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
513 {
514    DATA32  *dst_end = dst + dst_len;
515    Linear_Data  *gdata = (Linear_Data *)params_data;
516    int      off = gdata->off * (src_len - 1);
517    int      yy;
518
519    SETUP_LINEAR_FILL
520
521    if (ayx == 0)
522      {
523         DATA32  c;
524
525         y = (yy >> 16) + off;
526         y = y % src_len;
527         if (y < 0)
528            y += src_len;
529         c = src[y];
530         while (dst < dst_end)
531             *dst++ = c;
532         return;
533      }
534
535    if (ayy == 0)
536      {
537         Gfx_Func_Copy  func;
538         int  l;
539
540         x = (yy >> 16) + off;
541         x = x % src_len;
542         if (x < 0)
543            x += src_len;
544         if (ayx < 0)
545           {
546             l = x + 1;  x = 0;
547           }
548         else
549             l = src_len - x;
550         if (l > dst_len) l = dst_len;
551         func = evas_common_draw_func_copy_get(1, (ayx < 0 ? -1 : 0));
552         func(src + x, dst, l);
553         if (l == dst_len) return;
554         dst += l;  dst_len -= l;
555         l = dst_len / src_len;
556         while (l--)
557           {
558             func(src, dst, src_len);
559             dst += src_len;
560           }
561         l = dst_len % src_len;
562         if (ayx < 0)
563            src += src_len - l;
564         func(src, dst, l);
565         return;
566      }
567
568    while (dst < dst_end)
569      {
570         int  l = (yy >> 16);
571
572         l += ((yy - (l << 16)) >> 15) + off;
573         l = l % src_len;
574         if (l < 0)
575            l += src_len;
576         *dst++ = src[l];  yy += ayx;
577      }
578 }
579
580 static void
581 linear_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
582                  int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
583 {
584    DATA32  *dst_end = dst + dst_len;
585    Linear_Data  *gdata = (Linear_Data *)params_data;
586    int      off = gdata->off * (src_len - 1);
587    int      yy;
588
589    if (AXIS_ALIGNED)
590      {
591         linear_repeat(src, src_len, dst, mask, dst_len, x, y,
592                       axx, axy, ayx, ayy, params_data);
593         return;
594      }
595
596    SETUP_LINEAR_FILL
597
598 #ifdef BUILD_MMX
599    pxor_r2r(mm0, mm0);
600    MOV_A2R(ALPHA_255, mm5)
601 #endif
602    while (dst < dst_end)
603      {
604         int  l = (yy >> 16);
605         int  a = 1 + ((yy - (l << 16)) >> 8);
606
607         l += off;
608         l = l % src_len;
609         if (l < 0)
610            l += src_len;
611 #ifdef BUILD_MMX
612         MOV_P2R(src[l], mm1, mm0)
613 #else
614         *dst = src[l];
615 #endif
616         if (l + 1 < src_len)
617           {
618 #ifdef BUILD_MMX
619             INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
620 #else
621             *dst = INTERP_256(a, src[l + 1], *dst);
622 #endif
623           }
624         if (l == (src_len - 1))
625           {
626 #ifdef BUILD_MMX
627             INTERP_256_P2R(a, src[0], mm3, mm2, mm1, mm0)
628 #else
629            *dst = INTERP_256(a, src[0], *dst);
630 #endif
631           }
632 #ifdef BUILD_MMX
633         MOV_R2P(mm1, *dst, mm0)
634 #endif
635         dst++;  yy += ayx;
636      }
637 }
638
639 static void
640 linear_restrict(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
641                 int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
642 {
643    DATA32  *dst_end = dst + dst_len;
644    Linear_Data  *gdata = (Linear_Data *)params_data;
645    int      yy;
646
647    SETUP_LINEAR_FILL
648
649    if (ayx == 0)
650      {
651         DATA32  c;
652
653         y = (yy >> 16);
654         if ((y < 0) || (y >= src_len))
655           {
656             memset(dst, 0, sizeof(DATA32) * dst_len);
657             return;
658           }
659         c = src[y];
660         while (dst < dst_end)
661             *dst++ = c;
662         return;
663      }
664
665    if (ayy == 0)
666      {
667         Gfx_Func_Copy  func;
668
669         x = yy >> 16;
670         ayx = (ayx < 0 ? -1 : 1);
671         if ((unsigned)x < src_len)
672           {
673             if ((ayx > 0) && ((src_len - x) >= dst_len))
674               {
675                 func = evas_common_draw_func_copy_get(dst_len, 0);
676                 func(src + x, dst, dst_len);
677                 return;
678               }
679             if ((ayx < 0) && (x >= (dst_len - 1)))
680               {
681                 func = evas_common_draw_func_copy_get(dst_len, -1);
682                 func(src + x - (dst_len - 1), dst, dst_len);
683                 return;
684               }
685           }
686         while (dst < dst_end)
687           {
688             *dst = 0;
689             if ((unsigned)x < src_len)
690                 *dst = src[x];
691             dst++;  x += ayx;
692           }
693         return;
694      }
695
696    while (dst < dst_end)
697      {
698         int  l = (yy >> 16);
699
700         l += (yy - (l << 16)) >> 15;
701         *dst = 0;
702         if ((unsigned)l < src_len)
703             *dst = src[l];
704         dst++;  yy += ayx;
705      }
706 }
707
708 static void
709 linear_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
710                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
711 {
712    DATA32  *dst_end = dst + dst_len;
713    Linear_Data  *gdata = (Linear_Data *)params_data;
714    int      yy;
715
716    if (AXIS_ALIGNED)
717      {
718         linear_restrict(src, src_len, dst, mask, dst_len, x, y,
719                         axx, axy, ayx, ayy, params_data);
720         return;
721      }
722
723    SETUP_LINEAR_FILL
724
725 #ifdef BUILD_MMX
726    pxor_r2r(mm0, mm0);
727    MOV_A2R(ALPHA_255, mm5)
728 #endif
729    while (dst < dst_end)
730      {
731         int  l = (yy >> 16);
732
733         *dst = 0;
734         if ((unsigned)(l + 1) < (src_len + 1))
735           {
736             DATA32 a = 1 + ((yy - (l << 16)) >> 8);
737             int    lp = l;
738
739             if (l == -1) lp = 0;
740 #ifdef BUILD_MMX
741             MOV_P2R(src[lp], mm1, mm0)
742 #else
743             *dst = src[lp];
744 #endif
745             if (lp + 1 < src_len)
746               {
747 #ifdef BUILD_MMX
748                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
749 #else
750                 *dst = INTERP_256(a, src[lp + 1], *dst);
751 #endif
752               }
753             if (l == -1)
754               {
755 #ifdef BUILD_MMX
756                 MUL_256_A2R(a, mm3, mm1, mm0)
757 #else
758                 *dst = MUL_256(a, *dst);
759 #endif
760               }
761             if (l == (src_len - 1))
762               {
763 #ifdef BUILD_MMX
764                 a = 257 - a;
765                 MUL_256_A2R(a, mm3, mm1, mm0)
766 #else
767                 *dst = MUL_256(257 - a, *dst);
768 #endif
769               }
770 #ifdef BUILD_MMX
771             MOV_R2P(mm1, *dst, mm0)
772 #endif
773           }
774         dst++;  yy += ayx;
775      }
776 }
777
778 static void
779 linear_restrict_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
780                        int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
781 {
782    DATA32  *dst_end = dst + dst_len;
783    Linear_Data  *gdata = (Linear_Data *)params_data;
784    int      yy;
785
786    SETUP_LINEAR_FILL
787
788    if (ayx == 0)
789      {
790         DATA32  c;
791
792         y = (yy >> 16);
793         if ((y < 0) || (y >= src_len))
794           {
795             memset(dst, 0, sizeof(DATA32) * dst_len);
796             memset(mask, 0, sizeof(DATA8) * dst_len);
797             return;
798           }
799         c = src[y];
800         while (dst < dst_end)
801           {
802             *dst++ = c;  *mask++ = 255;
803           }
804         return;
805      }
806
807    if (ayy == 0)
808      {
809         Gfx_Func_Copy  func;
810
811         x = yy >> 16;
812         ayx = (ayx < 0 ? -1 : 1);
813         if ((unsigned)x < src_len)
814           {
815             if ((ayx > 0) && ((src_len - x) >= dst_len))
816               {
817                 func = evas_common_draw_func_copy_get(dst_len, 0);
818                 func(src + x, dst, dst_len);
819                 memset(mask, 255, sizeof(DATA8) * dst_len);
820                 return;
821               }
822             if ((ayx < 0) && (x >= (dst_len - 1)))
823               {
824                 func = evas_common_draw_func_copy_get(dst_len, -1);
825                 func(src + x - (dst_len - 1), dst, dst_len);
826                 memset(mask, 255, sizeof(DATA8) * dst_len);
827                 return;
828               }
829           }
830         while (dst < dst_end)
831           {
832             *dst = 0;  *mask = 0;
833             if ((unsigned)x < src_len)
834               {
835                 *dst = src[x];  *mask = 255;
836               }
837             dst++;  mask++;  x += ayx;
838           }
839         return;
840      }
841
842    while (dst < dst_end)
843      {
844         int  l = (yy >> 16);
845
846         l += (yy - (l << 16)) >> 15;
847         *dst = 0;  *mask = 0;
848         if ((unsigned)l < src_len)
849           {
850             *dst = src[l];  *mask = 255;
851           }
852         dst++;  mask++;  yy += ayx;
853      }
854 }
855
856 static void
857 linear_restrict_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
858                           int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
859 {
860    DATA32  *dst_end = dst + dst_len;
861    Linear_Data  *gdata = (Linear_Data *)params_data;
862    int      yy;
863
864    if (AXIS_ALIGNED)
865      {
866         linear_restrict_masked(src, src_len, dst, mask, dst_len, x, y,
867                                axx, axy, ayx, ayy, params_data);
868         return;
869      }
870
871    SETUP_LINEAR_FILL
872
873 #ifdef BUILD_MMX
874    pxor_r2r(mm0, mm0);
875    MOV_A2R(ALPHA_255, mm5)
876 #endif
877    while (dst < dst_end)
878      {
879         int  l = (yy >> 16);
880
881         *dst = 0;  *mask = 0;
882         if ((unsigned)(l + 1) < (src_len + 1))
883           {
884             DATA32 a = 1 + ((yy - (l << 16)) >> 8);
885             int    lp = l;
886
887             if (l == -1) lp = 0;
888
889 #ifdef BUILD_MMX
890             MOV_P2R(src[lp], mm1, mm0)
891 #else
892             *dst = src[lp];  *mask = 255;
893 #endif
894             if (lp + 1 < src_len)
895               {
896 #ifdef BUILD_MMX
897                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
898 #else
899                 *dst = INTERP_256(a, src[lp + 1], *dst);
900 #endif
901               }
902             if (l == -1)
903                 *mask = a - 1;
904             if (l == (src_len - 1))
905                 *mask = 256 - a;
906 #ifdef BUILD_MMX
907             MOV_R2P(mm1, *dst, mm0)
908 #endif
909           }
910         dst++;  mask++;  yy += ayx;
911      }
912 }
913
914 static void
915 linear_restrict_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
916                         int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
917 {
918    DATA32  *dst_end = dst + dst_len;
919    Linear_Data  *gdata = (Linear_Data *)params_data;
920    int      off = gdata->off * (src_len - 1);
921    int      yy;
922
923    SETUP_LINEAR_FILL
924
925    if (ayx == 0)
926      {
927         DATA32  c;
928
929         y = (yy >> 16);
930         if ((y < 0) || (y >= src_len))
931           {
932             memset(dst, 0, sizeof(DATA32) * dst_len);
933             return;
934           }
935         y += off;
936         if (y < 0) y = -y;
937         if (y >= src_len)
938           {
939             int  m = (y % (2 * src_len));
940
941             y = (y % src_len);
942             if (m >= src_len)
943                 y = src_len - y - 1;
944           }
945         c = src[y];
946         while (dst < dst_end)
947             *dst++ = c;
948         return;
949      }
950
951    while (dst < dst_end)
952      {
953         int  l = (yy >> 16);
954
955         l += (yy - (l << 16)) >> 15;
956         *dst = 0;
957         if ((unsigned)l < src_len)
958           {
959             l += off;
960             if (l < 0) l = -l;
961             if (l >= src_len)
962               {
963                 int  m = (l % (2 * src_len));
964
965                 l = (l % src_len);
966                 if (m >= src_len)
967                    l = src_len - l - 1;
968               }
969             *dst = src[l];
970           }
971         dst++;  yy += ayx;
972      }
973 }
974
975 static void
976 linear_restrict_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
977                            int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
978 {
979    DATA32  *dst_end = dst + dst_len;
980    Linear_Data  *gdata = (Linear_Data *)params_data;
981    int      off = gdata->off * (src_len - 1);
982    int      yy;
983
984    if (AXIS_ALIGNED)
985      {
986         linear_restrict_reflect(src, src_len, dst, mask, dst_len, x, y,
987                                 axx, axy, ayx, ayy, params_data);
988         return;
989      }
990
991    SETUP_LINEAR_FILL
992
993 #ifdef BUILD_MMX
994    pxor_r2r(mm0, mm0);
995    MOV_A2R(ALPHA_255, mm5)
996 #endif
997    while (dst < dst_end)
998      {
999         int  l = (yy >> 16);
1000
1001         *dst = 0;
1002         if ((unsigned)(l + 1) < (src_len + 1))
1003           {
1004             DATA32 a = 1 + ((yy - (l << 16)) >> 8), a0 = a;
1005             int    lp = l + off;
1006
1007             if (l == -1) lp = off;
1008             if (lp < 0) { lp = -lp;  a = 257 - a; }
1009             if (lp >= src_len)
1010               {
1011                 int  m = (lp % (2 * src_len));
1012
1013                 lp = (lp % src_len);
1014                 if (m >= src_len)
1015                   { lp = src_len - lp - 1;  a = 257 - a; }
1016               }
1017 #ifdef BUILD_MMX
1018             MOV_P2R(src[lp], mm1, mm0)
1019 #else
1020             *dst = src[lp];
1021 #endif
1022             if (lp + 1 < src_len)
1023               {
1024 #ifdef BUILD_MMX
1025                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
1026 #else
1027                 *dst = INTERP_256(a, src[lp + 1], *dst);
1028 #endif
1029               }
1030             if (l == -1)
1031               {
1032 #ifdef BUILD_MMX
1033                 MUL_256_A2R(a0, mm3, mm1, mm0)
1034 #else
1035                 *dst = MUL_256(a0, *dst);
1036 #endif
1037               }
1038             if (l == (src_len - 1))
1039               {
1040 #ifdef BUILD_MMX
1041                 a0 = 257 - a0;
1042                 MUL_256_A2R(a0, mm3, mm1, mm0)
1043 #else
1044                 *dst = MUL_256(257 - a0, *dst);
1045 #endif
1046               }
1047 #ifdef BUILD_MMX
1048             MOV_R2P(mm1, *dst, mm0)
1049 #endif
1050           }
1051         dst++;  yy += ayx;
1052      }
1053 }
1054
1055 static void
1056 linear_restrict_reflect_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1057                                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1058 {
1059    DATA32  *dst_end = dst + dst_len;
1060    Linear_Data  *gdata = (Linear_Data *)params_data;
1061    int      off = gdata->off * (src_len - 1);
1062    int      yy;
1063
1064    SETUP_LINEAR_FILL
1065
1066    if (ayx == 0)
1067      {
1068         DATA32  c;
1069
1070         y = (yy >> 16);
1071         if ((y < 0) || (y >= src_len))
1072           {
1073             memset(dst, 0, sizeof(DATA32) * dst_len);
1074             memset(mask, 0, sizeof(DATA8) * dst_len);
1075             return;
1076           }
1077         y += off;
1078         if (y < 0) y = -y;
1079         if (y >= src_len)
1080           {
1081             int  m = (y % (2 * src_len));
1082
1083             y = (y % src_len);
1084             if (m >= src_len)
1085                 y = src_len - y - 1;
1086           }
1087         c = src[y];
1088         while (dst < dst_end)
1089           { *dst++ = c;  *mask++ = 255; }
1090         return;
1091      }
1092
1093    while (dst < dst_end)
1094      {
1095         int  l = (yy >> 16);
1096
1097         l += ((yy - (l << 16)) >> 15);
1098         *dst = 0;  *mask = 0;
1099         if ((unsigned)l < src_len)
1100           {
1101             l += off;
1102             if (l < 0) l = -l;
1103             if (l >= src_len)
1104               {
1105                 int  m = (l % (2 * src_len));
1106
1107                 l = (l % src_len);
1108                 if (m >= src_len)
1109                    l = src_len - l - 1;
1110               }
1111             *dst = src[l];  *mask = 255;
1112           }
1113         dst++;  mask++;  yy += ayx;
1114      }
1115 }
1116
1117 static void
1118 linear_restrict_reflect_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1119                                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1120 {
1121    DATA32  *dst_end = dst + dst_len;
1122    Linear_Data  *gdata = (Linear_Data *)params_data;
1123    int      off = gdata->off * (src_len - 1);
1124    int      yy;
1125
1126    if (AXIS_ALIGNED)
1127      {
1128         linear_restrict_reflect_masked(src, src_len, dst, mask, dst_len, x, y,
1129                                        axx, axy, ayx, ayy, params_data);
1130         return;
1131      }
1132
1133    SETUP_LINEAR_FILL
1134
1135 #ifdef BUILD_MMX
1136    pxor_r2r(mm0, mm0);
1137    MOV_A2R(ALPHA_255, mm5)
1138 #endif
1139    while (dst < dst_end)
1140      {
1141         int  l = (yy >> 16);
1142
1143         *dst = 0;  *mask = 0;
1144         if ((unsigned)(l + 1) < (src_len + 1))
1145           {
1146             DATA32 a = 1 + ((yy - (l << 16)) >> 8), a0 = a - 1;
1147             int    lp = l + off;
1148
1149             if (l == -1) lp = off;
1150             if (lp < 0) { lp = -lp;  a = 257 - a; }
1151             if (lp >= src_len)
1152               {
1153                 int  m = (lp % (2 * src_len));
1154
1155                 lp = (lp % src_len);
1156                 if (m >= src_len)
1157                    { lp = src_len - lp - 1;  a = 257 - a; }
1158               }
1159 #ifdef BUILD_MMX
1160             MOV_P2R(src[lp], mm1, mm0)
1161 #else
1162             *dst = src[lp];
1163 #endif
1164             *mask = 255;
1165
1166             if (lp + 1 < src_len)
1167              {
1168 #ifdef BUILD_MMX
1169                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
1170 #else
1171                 *dst = INTERP_256(a, src[lp + 1], *dst);
1172 #endif
1173              }
1174 #ifdef BUILD_MMX
1175             MOV_R2P(mm1, *dst, mm0)
1176 #endif
1177             if (l == -1)
1178                 *mask = a0;
1179             if (l == (src_len - 1))
1180                 *mask = 255 - a0;
1181           }
1182         dst++;  mask++;  yy += ayx;
1183      }
1184 }
1185
1186 static void
1187 linear_restrict_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1188                        int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1189 {
1190    DATA32  *dst_end = dst + dst_len;
1191    Linear_Data  *gdata = (Linear_Data *)params_data;
1192    int      off = gdata->off * (src_len - 1);
1193    int      yy;
1194
1195    SETUP_LINEAR_FILL
1196
1197    if (ayx == 0)
1198      {
1199         DATA32  c;
1200
1201         y = (yy >> 16);
1202         if ((y < 0) || (y >= src_len))
1203           {
1204             memset(dst, 0, sizeof(DATA32) * dst_len);
1205             return;
1206           }
1207         y += off;
1208         y = y % src_len;
1209         if (y < 0)
1210            y += src_len;
1211         c = src[y];
1212         while (dst < dst_end)
1213             *dst++ = c;
1214         return;
1215      }
1216
1217    while (dst < dst_end)
1218      {
1219         int  l = (yy >> 16);
1220
1221         l += (yy - (l << 16)) >> 15;
1222         *dst = 0;
1223         if ((unsigned)l < src_len)
1224           {
1225             l += off;
1226             l = l % src_len;
1227             if (l < 0)
1228                 l += src_len;
1229             *dst = src[l];
1230           }
1231         dst++;  yy += ayx;
1232      }
1233 }
1234
1235 static void
1236 linear_restrict_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1237                           int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1238 {
1239    DATA32  *dst_end = dst + dst_len;
1240    Linear_Data  *gdata = (Linear_Data *)params_data;
1241    int      off = gdata->off * (src_len - 1);
1242    int      yy;
1243
1244    if (AXIS_ALIGNED)
1245      {
1246         linear_restrict_repeat(src, src_len, dst, mask, dst_len, x, y,
1247                                axx, axy, ayx, ayy, params_data);
1248         return;
1249      }
1250
1251    SETUP_LINEAR_FILL
1252
1253 #ifdef BUILD_MMX
1254    pxor_r2r(mm0, mm0);
1255    MOV_A2R(ALPHA_255, mm5)
1256 #endif
1257    while (dst < dst_end)
1258      {
1259         int  l = (yy >> 16);
1260
1261         *dst = 0;
1262         if ((unsigned)(l + 1) < (src_len + 1))
1263           {
1264             DATA32 a = 1 + ((yy - (l << 16)) >> 8);
1265             int    lp = l + off;
1266
1267             if (l == -1) lp = off;
1268             lp = lp % src_len;
1269             if (lp < 0)
1270                 lp += src_len;
1271 #ifdef BUILD_MMX
1272             MOV_P2R(src[lp], mm1, mm0)
1273 #else
1274             *dst = src[lp];
1275 #endif
1276             if (lp + 1 < src_len)
1277               {
1278 #ifdef BUILD_MMX
1279                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
1280 #else
1281                 *dst = INTERP_256(a, src[lp + 1], *dst);
1282 #endif
1283               }
1284             if (lp == (src_len - 1))
1285               {
1286 #ifdef BUILD_MMX
1287                 INTERP_256_P2R(a, src[0], mm3, mm2, mm1, mm0)
1288 #else
1289                 *dst = INTERP_256(a, src[0], *dst);
1290 #endif
1291               }
1292             if (l == -1)
1293               {
1294 #ifdef BUILD_MMX
1295                 MUL_256_A2R(a, mm3, mm1, mm0)
1296 #else
1297                 *dst = MUL_256(a, *dst);
1298 #endif
1299               }
1300             if (l == (src_len - 1))
1301               {
1302 #ifdef BUILD_MMX
1303                 a = 257 - a;
1304                 MUL_256_A2R(a, mm3, mm1, mm0)
1305 #else
1306                 *dst = MUL_256(257 - a, *dst);
1307 #endif
1308               }
1309 #ifdef BUILD_MMX
1310             MOV_R2P(mm1, *dst, mm0)
1311 #endif
1312           }
1313         dst++;  yy += ayx;
1314      }
1315 }
1316
1317 static void
1318 linear_restrict_repeat_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1319                               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1320 {
1321    DATA32  *dst_end = dst + dst_len;
1322    Linear_Data  *gdata = (Linear_Data *)params_data;
1323    int      off = gdata->off * (src_len - 1);
1324    int      yy;
1325
1326    SETUP_LINEAR_FILL
1327
1328    if (ayx == 0)
1329      {
1330         DATA32  c;
1331
1332         y = (yy >> 16);
1333         if ((y < 0) || (y >= src_len))
1334           {
1335             memset(dst, 0, sizeof(DATA32) * dst_len);
1336             memset(mask, 0, sizeof(DATA8) * dst_len);
1337             return;
1338           }
1339         y += off;
1340         y = y % src_len;
1341         if (y < 0)
1342            y += src_len;
1343         c = src[y];
1344         while (dst < dst_end)
1345           { *dst++ = c;  *mask++ = 255; }
1346         return;
1347      }
1348
1349    while (dst < dst_end)
1350      {
1351         int  l = (yy >> 16);
1352
1353         l += ((yy - (l << 16)) >> 15);
1354         *dst = 0;  *mask = 0;
1355         if ((unsigned)l < src_len)
1356           {
1357             l += off;
1358             l = l % src_len;
1359             if (l < 0)
1360                 l += src_len;
1361             *dst = src[l];  *mask = 255;
1362           }
1363         dst++;  mask++;  yy += ayx;
1364      }
1365 }
1366
1367 static void
1368 linear_restrict_repeat_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1369                                  int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1370 {
1371    DATA32  *dst_end = dst + dst_len;
1372    Linear_Data  *gdata = (Linear_Data *)params_data;
1373    int      off = gdata->off * (src_len - 1);
1374    int      yy;
1375
1376    if (AXIS_ALIGNED)
1377      {
1378         linear_restrict_repeat_masked(src, src_len, dst, mask, dst_len, x, y,
1379                                       axx, axy, ayx, ayy, params_data);
1380         return;
1381      }
1382
1383    SETUP_LINEAR_FILL
1384
1385 #ifdef BUILD_MMX
1386    pxor_r2r(mm0, mm0);
1387    MOV_A2R(ALPHA_255, mm5)
1388 #endif
1389    while (dst < dst_end)
1390      {
1391         int  l = (yy >> 16);
1392
1393         *dst = 0;  *mask = 0;
1394         if ((unsigned)(l + 1) < (src_len + 1))
1395           {
1396             DATA32 a = 1 + ((yy - (l << 16)) >> 8);
1397             int    lp = l + off;
1398
1399             if (l == -1) lp = off;
1400             lp = lp % src_len;
1401             if (lp < 0)
1402                 lp += src_len;
1403 #ifdef BUILD_MMX
1404             MOV_P2R(src[lp], mm1, mm0)
1405 #else
1406             *dst = src[lp];
1407 #endif
1408             *mask = 255;
1409
1410             if (lp + 1 < src_len)
1411              {
1412 #ifdef BUILD_MMX
1413                 INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
1414 #else
1415                 *dst = INTERP_256(a, src[lp + 1], *dst);
1416 #endif
1417              }
1418             if (lp == (src_len - 1))
1419              {
1420 #ifdef BUILD_MMX
1421                 INTERP_256_P2R(a, src[0], mm3, mm2, mm1, mm0)
1422 #else
1423                 *dst = INTERP_256(a, src[0], *dst);
1424 #endif
1425              }
1426 #ifdef BUILD_MMX
1427             MOV_R2P(mm1, *dst, mm0)
1428 #endif
1429             if (l == -1)
1430                 *mask = a - 1;
1431             if (l == (src_len - 1))
1432                 *mask = 256 - a;
1433           }
1434         dst++;  mask++;  yy += ayx;
1435      }
1436 }
1437
1438 static void
1439 linear_pad(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1440            int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1441 {
1442    DATA32  *dst_end = dst + dst_len;
1443    Linear_Data  *gdata = (Linear_Data *)params_data;
1444    int      yy;
1445
1446    SETUP_LINEAR_FILL
1447
1448    while (dst < dst_end)
1449      {
1450         int  l = (yy >> 16);
1451
1452         l += (yy - (l << 16)) >> 15;
1453         if (l < 0) l = 0;
1454         if (l >= src_len) l = src_len - 1;
1455         *dst = src[l];
1456         dst++;  yy += ayx;
1457      }
1458 }
1459
1460 static void
1461 linear_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
1462               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
1463 {
1464    DATA32  *dst_end = dst + dst_len;
1465    Linear_Data  *gdata = (Linear_Data *)params_data;
1466    int      yy;
1467
1468    if (AXIS_ALIGNED)
1469      {
1470         linear_pad(src, src_len, dst, mask, dst_len, x, y,
1471                    axx, axy, ayx, ayy, params_data);
1472         return;
1473      }
1474
1475    SETUP_LINEAR_FILL
1476
1477 #ifdef BUILD_MMX
1478    pxor_r2r(mm0, mm0);
1479    MOV_A2R(ALPHA_255, mm5)
1480 #endif
1481    while (dst < dst_end)
1482      {
1483         int  l = (yy >> 16);
1484
1485         if (l < 0) *dst = src[0];
1486         if (l >= src_len) *dst = src[src_len - 1];
1487         if ((unsigned)l < src_len)
1488           {
1489             DATA32 a = 1 + ((yy - (l << 16)) >> 8);
1490
1491 #ifdef BUILD_MMX
1492             MOV_P2R(src[l], mm1, mm0)
1493 #else
1494             *dst = src[l];
1495 #endif
1496             if (l && (l + 1 < src_len))
1497               {
1498 #ifdef BUILD_MMX
1499                 INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
1500 #else
1501                 *dst = INTERP_256(a, src[l + 1], *dst);
1502 #endif
1503               }
1504 #ifdef BUILD_MMX
1505             MOV_R2P(mm1, *dst, mm0)
1506 #endif
1507           }
1508         dst++;  yy += ayx;
1509      }
1510 }