use float constants instead of double as computations
[framework/uifw/evas.git] / src / lib / engines / common / evas_gradient_sinusoidal.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 typedef struct _Sinusoidal_Data   Sinusoidal_Data;
11 struct _Sinusoidal_Data
12 {
13    float  amp, per;
14
15    float  sa, sp;
16    float  off;
17    int    len;
18 };
19
20 static void
21 sinusoidal_init(void);
22
23 static void
24 sinusoidal_shutdown(void);
25
26 static void
27 sinusoidal_init_geom(RGBA_Gradient *gr);
28
29 static void
30 sinusoidal_setup_geom(RGBA_Gradient *gr);
31
32 static void
33 sinusoidal_free_geom(void *gdata);
34
35 static int
36 sinusoidal_has_alpha(RGBA_Gradient *gr, int op);
37
38 static int
39 sinusoidal_has_mask(RGBA_Gradient *gr, int op);
40
41 static int
42 sinusoidal_get_map_len(RGBA_Gradient *gr);
43
44 static Gfx_Func_Gradient_Fill
45 sinusoidal_get_fill_func(RGBA_Gradient *gr, int op, unsigned char aa);
46
47 static RGBA_Gradient_Type  sinusoidal = {"sinusoidal", sinusoidal_init, sinusoidal_shutdown,
48                                          sinusoidal_init_geom, sinusoidal_setup_geom, sinusoidal_free_geom,
49                                          sinusoidal_has_alpha, sinusoidal_has_mask,
50                                          sinusoidal_get_map_len, sinusoidal_get_fill_func};
51
52
53 /** internal functions **/
54
55 static void
56 sinusoidal_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
57                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
58
59 static void
60 sinusoidal_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
61                       int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
62
63 static void
64 sinusoidal_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
65                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
66
67 static void
68 sinusoidal_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
69                      int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
70
71 static void
72 sinusoidal_restrict_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
73                             int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
74
75 static void
76 sinusoidal_restrict_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
77                                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
78
79 static void
80 sinusoidal_restrict_reflect_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
81                                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
82
83 static void
84 sinusoidal_restrict_reflect_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
85                                       int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
86
87 static void
88 sinusoidal_restrict_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
89                            int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
90
91 static void
92 sinusoidal_restrict_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
93                               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
94
95 static void
96 sinusoidal_restrict_repeat_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
97                                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
98
99 static void
100 sinusoidal_restrict_repeat_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
101                                      int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
102
103 static void
104 sinusoidal_pad(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
105                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
106
107 static void
108 sinusoidal_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
109                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data);
110
111
112 RGBA_Gradient_Type  *
113 evas_common_gradient_sinusoidal_get(void)
114 {
115     return &sinusoidal;
116 }
117
118 static void
119 sinusoidal_init(void)
120 {
121 }
122
123 static void
124 sinusoidal_shutdown(void)
125 {
126 }
127
128 static void
129 sinusoidal_free_geom(void *gdata)
130 {
131    Sinusoidal_Data *data = (Sinusoidal_Data *)gdata;
132    if (data) free(data);
133 }
134
135 static void
136 sinusoidal_setup_geom(RGBA_Gradient *gr)
137 {
138    Sinusoidal_Data   *sinusoidal_data;
139
140    if (!gr || (gr->type.geometer != &sinusoidal)) return;
141
142    sinusoidal_data = (Sinusoidal_Data *)gr->type.gdata;
143    if (!sinusoidal_data) return;
144    sinusoidal_data->sa = sinusoidal_data->amp * gr->fill.h;
145    sinusoidal_data->sp = sinusoidal_data->per * (M_PI / gr->fill.w);
146    sinusoidal_data->off = gr->map.offset;
147    sinusoidal_data->len = gr->fill.h;
148 }
149
150 static void
151 sinusoidal_init_geom(RGBA_Gradient *gr)
152 {
153    Sinusoidal_Data   *sinusoidal_data;
154    int    err = 1;
155    char   *s, *p, key[256];
156    float  amp, per, val;
157
158    if (!gr || (gr->type.geometer != &sinusoidal)) return;
159
160    sinusoidal_data = (Sinusoidal_Data *)gr->type.gdata;
161    if (!sinusoidal_data)
162      {
163         sinusoidal_data = calloc(1, sizeof(Sinusoidal_Data));
164         if (!sinusoidal_data)  return;
165         sinusoidal_data->amp = 1.0;
166         sinusoidal_data->per = 1.0;
167         sinusoidal_data->sa = 32;
168         sinusoidal_data->sp = M_PI / 32;
169         sinusoidal_data->off = 0.0;
170         sinusoidal_data->len = 32;
171      }
172    gr->type.gdata = sinusoidal_data;
173
174    if (!gr->type.params || !*(gr->type.params))
175         return;
176
177    s = strdup(gr->type.params);
178    if (!s) return;
179
180    amp = sinusoidal_data->amp;
181    per = sinusoidal_data->per;
182    p = s;
183    while ((p = evas_common_gradient_get_key_fval(p, key, &val)))
184      {
185         if (!strcmp(key, "amplitude"))
186           {
187             err = 0;
188             amp = val;
189           }
190         else if (!strcmp(key, "period"))
191           {
192             err = 0;
193             per = val;
194           }
195         else
196           {
197             err = 1;
198             break;
199           }
200      }
201    if (!err)
202      {
203         sinusoidal_data->amp = amp;
204         if (per < 0.0) per = -per;
205         sinusoidal_data->per = per;
206      }
207    free(s);
208 }
209
210
211 static int
212 sinusoidal_has_alpha(RGBA_Gradient *gr, int op)
213 {
214    if (!gr || (gr->type.geometer != &sinusoidal)) return 0;
215
216    if (gr->has_alpha | gr->map.has_alpha)
217         return 1;
218    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
219          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
220         return 0;
221    if ( (gr->fill.spread == _EVAS_TEXTURE_RESTRICT) ||
222          (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REFLECT) ||
223          (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REPEAT) )
224         return 1;
225    return 0;
226 }
227
228 static int
229 sinusoidal_has_mask(RGBA_Gradient *gr, int op)
230 {
231    if (!gr || (gr->type.geometer != &sinusoidal)) return 0;
232    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
233          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
234      {
235         if ( (gr->fill.spread == _EVAS_TEXTURE_RESTRICT) ||
236               (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REFLECT) ||
237               (gr->fill.spread == _EVAS_TEXTURE_RESTRICT_REPEAT) )
238             return 1;
239      }
240
241    return 0;
242 }
243
244 static int
245 sinusoidal_get_map_len(RGBA_Gradient *gr)
246 {
247    Sinusoidal_Data   *sinusoidal_data;
248
249    if (!gr || (gr->type.geometer != &sinusoidal)) return 0;
250    sinusoidal_data = (Sinusoidal_Data *)gr->type.gdata;
251    if (!sinusoidal_data) return 0;
252    return sinusoidal_data->len;
253 }
254
255 static Gfx_Func_Gradient_Fill
256 sinusoidal_get_fill_func(RGBA_Gradient *gr, int op, unsigned char aa)
257 {
258    Sinusoidal_Data   *sinusoidal_data;
259    Gfx_Func_Gradient_Fill  sfunc = NULL;
260    int masked_op = 0;
261
262    if (!gr || (gr->type.geometer != &sinusoidal))
263         return sfunc;
264    sinusoidal_data = (Sinusoidal_Data *)gr->type.gdata;
265    if (!sinusoidal_data) return sfunc;
266
267    sinusoidal_data->off = gr->map.offset;
268    if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) ||
269          (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
270         masked_op = 1;
271
272    switch (gr->fill.spread)
273      {
274       case _EVAS_TEXTURE_REFLECT:
275         {
276          if (aa)
277             sfunc = sinusoidal_reflect_aa;
278          else
279             sfunc = sinusoidal_reflect;
280         }
281       break;
282       case _EVAS_TEXTURE_REPEAT:
283         {
284          if (aa)
285             sfunc = sinusoidal_repeat_aa;
286          else
287             sfunc = sinusoidal_repeat;
288         }
289       break;
290       case _EVAS_TEXTURE_RESTRICT:
291          sinusoidal_data->off = 0;
292       case _EVAS_TEXTURE_RESTRICT_REFLECT:
293         {
294          if (aa)
295            {
296             if (masked_op)
297                 sfunc = sinusoidal_restrict_reflect_aa_masked;
298             else
299                 sfunc = sinusoidal_restrict_reflect_aa;
300            }
301          else
302            {
303             if (masked_op)
304                 sfunc = sinusoidal_restrict_reflect_masked;
305             else
306                 sfunc = sinusoidal_restrict_reflect;
307            }
308         }
309       break;
310       case _EVAS_TEXTURE_RESTRICT_REPEAT:
311         {
312          if (aa)
313            {
314             if (masked_op)
315                 sfunc = sinusoidal_restrict_repeat_aa_masked;
316             else
317                 sfunc = sinusoidal_restrict_repeat_aa;
318            }
319          else
320            {
321             if (masked_op)
322                 sfunc = sinusoidal_restrict_repeat_masked;
323             else
324                 sfunc = sinusoidal_restrict_repeat;
325            }
326         }
327       break;
328       case _EVAS_TEXTURE_PAD:
329         {
330          if (aa)
331             sfunc = sinusoidal_pad_aa;
332          else
333             sfunc = sinusoidal_pad;
334         }
335       break;
336       default:
337         sfunc = sinusoidal_reflect_aa;
338       break;
339      }
340    return sfunc;
341 }
342
343 #define SETUP_SINU_FILL \
344    a00 = gdata->sp * (axx / 65536.0f); \
345    a01 = gdata->sp * (axy / 65536.0f); \
346    a10 = ayx / 65536.0f; \
347    a11 = ayy / 65536.0f; \
348    xf = (a00 * x) + (a01 * y); \
349    yf = (a10 * x) + (a11 * y);
350
351 static void
352 sinusoidal_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
353                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
354 {
355    DATA32  *dst_end = dst + dst_len;
356    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
357    float  xf, yf, sa = gdata->sa;
358    float  a00, a01, a10, a11;
359    float  off = gdata->off * (src_len - 1);
360
361    SETUP_SINU_FILL
362
363    while (dst < dst_end)
364      {
365         int  l = (yf - (sa * sin(xf))) + off;
366
367         if (l < 0)  l = -l;
368         if (l >= src_len)
369           {
370             int  m = (l % (2 * src_len));
371
372             l = (l % src_len);
373             if (m >= src_len)
374                 l = src_len - l - 1;
375           }
376         *dst++ = src[l];  xf += a00;  yf += a10;
377      }
378 }
379
380 static void
381 sinusoidal_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
382                       int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
383 {
384    DATA32  *dst_end = dst + dst_len;
385    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
386    float  xf, yf, sa = gdata->sa;
387    float  a00, a01, a10, a11;
388    float  off = gdata->off * (src_len - 1);
389
390    SETUP_SINU_FILL
391
392    while (dst < dst_end)
393      {
394         float  r = (yf - (sa * sin(xf))) + off;
395         int    l = r, a;
396
397         if (r < 0)  r = -r;
398         a = 1 + (int)(255 * (r - (int)r));
399
400         if (l < 0)  l = -l;
401         if (l >= src_len)
402           {
403             int  m = (l % (2 * src_len));
404
405             l = (l % src_len);
406             if (m >= src_len)
407                 { l = src_len - l - 1;  a = 257 - a; }
408           }
409         *dst = src[l];
410         if (l + 1 < src_len)
411           *dst = INTERP_256(a, src[l + 1], *dst);
412
413         dst++;  xf += a00;  yf += a10;
414      }
415 }
416
417 static void
418 sinusoidal_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
419                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
420 {
421    DATA32  *dst_end = dst + dst_len;
422    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
423    float  xf, yf, sa = gdata->sa;
424    float  a00, a01, a10, a11;
425    float  off = gdata->off * (src_len - 1);
426
427    SETUP_SINU_FILL
428
429    while (dst < dst_end)
430      {
431         int  l = (yf - (sa * sin(xf))) + off;
432
433         l = (l % src_len);
434         if (l < 0)
435             l += src_len;
436         *dst++ = src[l];  xf += a00;  yf += a10;
437      }
438 }
439
440 static void
441 sinusoidal_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
442                      int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
443 {
444    DATA32  *dst_end = dst + dst_len;
445    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
446    float  xf, yf, sa = gdata->sa;
447    float  a00, a01, a10, a11;
448    float  off = gdata->off * (src_len - 1);
449
450    SETUP_SINU_FILL
451
452    while (dst < dst_end)
453      {
454         float  r = (yf - (sa * sin(xf))) + off;
455         int    l = r, a;
456
457         if (r < 0) r = -r;
458         a = 1 + (int)(255 * (r - (int)r));
459
460         l = l % src_len;
461         if (l < 0)
462           { l += src_len;  a = 257 - a; }
463
464         *dst = src[l];
465         if (l + 1 < src_len)
466            *dst = INTERP_256(a, src[l + 1], *dst);
467         if (l == (src_len - 1))
468            *dst = INTERP_256(a, src[0], *dst);
469         dst++;  xf += a00;  yf += a10;
470      }
471 }
472
473 static void
474 sinusoidal_restrict_reflect(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
475                             int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
476 {
477    DATA32  *dst_end = dst + dst_len;
478    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
479    float  xf, yf, sa = gdata->sa;
480    float  a00, a01, a10, a11;
481    float  off = gdata->off * (src_len - 1);
482
483    SETUP_SINU_FILL
484
485    while (dst < dst_end)
486      {
487         int  l = (yf - (sa * sin(xf)));
488
489         *dst = 0;
490         if ((unsigned)l < src_len)
491           {
492             l += off;
493             if (l < 0) l = -l;
494             if (l >= src_len)
495               {
496                 int  m = (l % (2 * src_len));
497
498                 l = (l % src_len);
499                 if (m >= src_len)
500                    l = src_len - l - 1;
501               }
502             *dst = src[l];
503           }
504         dst++;  xf += a00;  yf += a10;
505      }
506 }
507
508 static void
509 sinusoidal_restrict_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
510                                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
511 {
512    DATA32  *dst_end = dst + dst_len;
513    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
514    float  xf, yf, sa = gdata->sa;
515    float  a00, a01, a10, a11;
516    float  off = gdata->off * (src_len - 1);
517
518    SETUP_SINU_FILL
519
520    while (dst < dst_end)
521      {
522         float  r = (yf - (sa * sin(xf))) + off, s = r - off;
523         int    l = s;
524
525         *dst = 0;
526         if ((unsigned)l < src_len)
527           {
528             int  a, lp = r;
529
530             if (r < 0)  r = -r;
531             a = 1 + (int)(255 * (r - (int)r));
532             if (lp < 0) lp = -lp;
533             if (lp >= src_len)
534               {
535                 int  m = (lp % (2 * src_len));
536
537                 lp = (lp % src_len);
538                 if (m >= src_len)
539                   { lp = src_len - lp - 1;  a = 257 - a; }
540               }
541             *dst = src[lp];
542             if (lp + 1 < src_len)
543                 *dst = INTERP_256(a, src[lp + 1], *dst);
544             if ((l == 0) && (s < 0))
545               {
546                 a = 256 + (255 * s);
547                 *dst = MUL_256(a, *dst);
548               }
549             if (l == (src_len - 1))
550               {
551                 a = 256 - (255 * (s - l));
552                 *dst = MUL_256(a, *dst);
553               }
554           }
555         dst++;  xf += a00;  yf += a10;
556      }
557 }
558
559 static void
560 sinusoidal_restrict_reflect_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
561                                    int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
562 {
563    DATA32  *dst_end = dst + dst_len;
564    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
565    float  xf, yf, sa = gdata->sa;
566    float  a00, a01, a10, a11;
567    float  off = gdata->off * (src_len - 1);
568
569    SETUP_SINU_FILL
570
571    while (dst < dst_end)
572      {
573         int  l = (yf - (sa * sin(xf)));
574
575         *dst = 0;  *mask = 0;
576         if ((unsigned)l < src_len)
577           {
578             l += off;
579             if (l < 0) l = -l;
580             if (l >= src_len)
581               {
582                 int  m = (l % (2 * src_len));
583
584                 l = (l % src_len);
585                 if (m >= src_len)
586                    l = src_len - l - 1;
587               }
588             *dst = src[l];  *mask = 255;
589           }
590         dst++;  mask++;  xf += a00;  yf += a10;
591      }
592 }
593
594 static void
595 sinusoidal_restrict_reflect_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
596                                       int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
597 {
598    DATA32  *dst_end = dst + dst_len;
599    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
600    float  xf, yf, sa = gdata->sa;
601    float  a00, a01, a10, a11;
602    float  off = gdata->off * (src_len - 1);
603
604    SETUP_SINU_FILL
605
606    while (dst < dst_end)
607      {
608         float  r = (yf - (sa * sin(xf))) + off, s = r - off;
609         int    l = s;
610
611         *dst = 0;  *mask = 0;
612         if ((unsigned)l < src_len)
613           {
614             int  a, lp = r;
615
616             if (r < 0)  r = -r;
617             a = 1 + (int)(255 * (r - (int)r));
618             if (lp < 0) lp = -lp;
619             if (lp >= src_len)
620               {
621                 int  m = (lp % (2 * src_len));
622
623                 lp = (lp % src_len);
624                 if (m >= src_len)
625                   { lp = src_len - lp - 1;  a = 257 - a; }
626               }
627             *dst = src[lp];  *mask = 255;
628             if (lp + 1 < src_len)
629                 *dst = INTERP_256(a, src[lp + 1], *dst);
630             if ((l == 0) && (s < 0))
631                 *mask = 255 + (255 * s);
632             if (l == (src_len - 1))
633                 *mask = 255 - (255 * (s - l));
634           }
635         dst++;  mask++;  xf += a00;  yf += a10;
636      }
637 }
638
639 static void
640 sinusoidal_restrict_repeat(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, 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    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
645    float  xf, yf, sa = gdata->sa;
646    float  a00, a01, a10, a11;
647    float  off = gdata->off * (src_len - 1);
648
649    SETUP_SINU_FILL
650
651    while (dst < dst_end)
652      {
653         int  l = (yf - (sa * sin(xf)));
654
655         *dst = 0;
656         if ((unsigned)l < src_len)
657           {
658             l += off;
659             l = l % src_len;
660             if (l < 0)
661                 l += src_len;
662             *dst = src[l];
663           }
664         dst++;  xf += a00;  yf += a10;
665      }
666 }
667
668 static void
669 sinusoidal_restrict_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
670                               int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
671 {
672    DATA32  *dst_end = dst + dst_len;
673    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
674    float  xf, yf, sa = gdata->sa;
675    float  a00, a01, a10, a11;
676    float  off = gdata->off * (src_len - 1);
677
678    SETUP_SINU_FILL
679
680    while (dst < dst_end)
681      {
682         float  r = (yf - (sa * sin(xf))) + off, s = r - off;
683         int    l = s;
684
685         *dst = 0;
686         if ((unsigned)l < src_len)
687           {
688             int  a, lp = r;
689
690             if (r < 0)  r = -r;
691             a = 1 + (int)(255 * (r - (int)r));
692             lp = lp % src_len;
693             if (lp < 0)
694               { lp += src_len;  a = 257 - a; }
695             *dst = src[lp];
696             if (lp + 1 < src_len)
697                 *dst = INTERP_256(a, src[lp + 1], *dst);
698             if (lp == (src_len - 1))
699                 *dst = INTERP_256(a, src[0], *dst);
700             if ((l == 0) && (s < 0))
701               {
702                 a = 256 + (255 * s);
703                 *dst = MUL_256(a, *dst);
704               }
705             if (l == (src_len - 1))
706               {
707                 a = 256 - (255 * (s - l));
708                 *dst = MUL_256(a, *dst);
709               }
710           }
711         dst++;  xf += a00;  yf += a10;
712      }
713 }
714
715 static void
716 sinusoidal_restrict_repeat_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
717                                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
718 {
719    DATA32  *dst_end = dst + dst_len;
720    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
721    float  xf, yf, sa = gdata->sa;
722    float  a00, a01, a10, a11;
723    float  off = gdata->off * (src_len - 1);
724
725    SETUP_SINU_FILL
726
727    while (dst < dst_end)
728      {
729         int  l = (yf - (sa * sin(xf)));
730
731         *dst = 0;  *mask = 0;
732         if ((unsigned)l < src_len)
733           {
734             l += off;
735             l = l % src_len;
736             if (l < 0)
737                 l += src_len;
738             *dst = src[l];  *mask = 255;
739           }
740         dst++;  mask++;  xf += a00;  yf += a10;
741      }
742 }
743
744 static void
745 sinusoidal_restrict_repeat_aa_masked(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
746                                      int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
747 {
748    DATA32  *dst_end = dst + dst_len;
749    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
750    float  xf, yf, sa = gdata->sa;
751    float  a00, a01, a10, a11;
752    float  off = gdata->off * (src_len - 1);
753
754    SETUP_SINU_FILL
755
756    while (dst < dst_end)
757      {
758         float  r = (yf - (sa * sin(xf))) + off, s = r - off;
759         int    l = s;
760
761         *dst = 0;  *mask = 0;
762         if ((unsigned)l < src_len)
763           {
764             int  a, lp = r;
765
766             if (r < 0)  r = -r;
767             a = 1 + (int)(255 * (r - (int)r));
768             lp = lp % src_len;
769             if (lp < 0)
770               { lp += src_len;  a = 257 - a; }
771             *dst = src[lp];  *mask = 255;
772             if (lp + 1 < src_len)
773                 *dst = INTERP_256(a, src[lp + 1], *dst);
774             if (lp == (src_len - 1))
775                 *dst = INTERP_256(a, src[0], *dst);
776             if ((l == 0) && (s < 0))
777                 *mask = 255 + (255 * s);
778             if (l == (src_len - 1))
779                 *mask = 255 - (255 * (s - l));
780           }
781         dst++;  mask++;  xf += a00;  yf += a10;
782      }
783 }
784
785 static void
786 sinusoidal_pad(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
787                int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
788 {
789    DATA32  *dst_end = dst + dst_len;
790    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
791    float  xf, yf, sa = gdata->sa;
792    float  a00, a01, a10, a11;
793
794    SETUP_SINU_FILL
795
796    while (dst < dst_end)
797      {
798         int  l = (yf - (sa * sin(xf)));
799
800         if (l < 0)
801             l = 0;
802         if (l >= src_len)
803             l = src_len - 1;
804         *dst = src[l];
805         dst++;  xf += a00;  yf += a10;
806      }
807 }
808
809 static void
810 sinusoidal_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask __UNUSED__, int dst_len,
811                   int x, int y, int axx, int axy, int ayx, int ayy, void *params_data)
812 {
813    DATA32  *dst_end = dst + dst_len;
814    Sinusoidal_Data  *gdata = (Sinusoidal_Data *)params_data;
815    float  xf, yf, sa = gdata->sa;
816    float  a00, a01, a10, a11;
817
818    SETUP_SINU_FILL
819
820    while (dst < dst_end)
821      {
822         float  r = (yf - (sa * sin(xf)));
823         int    l = r;
824
825         *dst = 0;
826         if ((unsigned)l < (src_len - 1))
827           {
828             int  a;
829
830             if (r < 0) r = -r;
831             a = 1 + (int)(255 * (r - (int)r));
832             *dst = INTERP_256(a, src[l + 1], src[l]);
833           }
834         if (l < 0) *dst = src[0];
835         if (l >= src_len) *dst = src[src_len - 1];
836         dst++;  xf += a00;  yf += a10;
837      }
838 }