1 /* Utility functions for the filters.  */
2 
3 #include "evas_filter_private.h"
4 
5 Evas_Filter_Buffer *
evas_filter_buffer_scaled_get(Evas_Filter_Context * ctx,Evas_Filter_Buffer * src,unsigned w,unsigned h)6 evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
7                               Evas_Filter_Buffer *src,
8                               unsigned w, unsigned h)
9 {
10    unsigned int src_len = 0, src_stride, dst_len = 0, dst_stride;
11    uint8_t *src_map = NULL, *dst_map = NULL;
12    Evas_Filter_Buffer *dst;
13    RGBA_Image dstim, srcim;
14    RGBA_Draw_Context dc;
15    Eina_Bool ok;
16 
17    DBG("Scaling buffer from %dx%d to %dx%d, this is a slow operation!",
18        src->w, src->h, w, h);
19    DEBUG_TIME_BEGIN();
20 
21    // Get destination buffer
22    dst = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only, 0);
23    EINA_SAFETY_ON_NULL_RETURN_VAL(dst, NULL);
24 
25    // Map input and output
26    src_map = _buffer_map_all(src->buffer, &src_len, E_READ, E_ARGB, &src_stride);
27    dst_map = _buffer_map_all(dst->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
28    EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map, end);
29    EINA_SAFETY_ON_FALSE_GOTO((src_stride == ((unsigned) src->w * 4)) &&
30                              (dst_stride == (w * 4)), end);
31 
32    // Wrap as basic RGBA_Images
33    memset(&dstim, 0, sizeof(dstim));
34    dstim.cache_entry.w = w;
35    dstim.cache_entry.h = h;
36    dstim.cache_entry.flags.alpha = 1;
37    dstim.cache_entry.flags.alpha_sparse = 0;
38    dstim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
39    dstim.image.data8 = dst_map;
40 
41    memset(&srcim, 0, sizeof(srcim));
42    srcim.cache_entry.w = src->w;
43    srcim.cache_entry.h = src->h;
44    srcim.cache_entry.flags.alpha = 1;
45    srcim.cache_entry.flags.alpha_sparse = 0;
46    srcim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
47    srcim.image.data8 = src_map;
48 
49    // Basic draw context
50    memset(&dc, 0, sizeof(dc));
51    dc.render_op = EVAS_RENDER_COPY;
52 
53    // Do the scale
54    ok = evas_common_scale_rgba_in_to_out_clip_smooth
55          (&srcim, &dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
56 
57    if (!ok)
58      {
59        ERR("RGBA Image scaling failed.");
60        dst = NULL;
61      }
62 
63 end:
64    if (src_map) ector_buffer_unmap(src->buffer, src_map, src_len);
65    if ((dst) && (dst_map))
66      ector_buffer_unmap(dst->buffer, dst_map, dst_len);
67    DEBUG_TIME_END();
68    return dst;
69 }
70 
71 static Eina_Bool
_interpolate_none(DATA8 * output,int * points)72 _interpolate_none(DATA8 *output, int *points)
73 {
74    DATA8 val = 0;
75    int j;
76    for (j = 0; j < 256; j++)
77      {
78         if (points[j] == -1)
79           output[j] = val;
80         else
81           val = output[j] = (DATA8) points[j];
82      }
83    return EINA_TRUE;
84 }
85 
86 static Eina_Bool
_interpolate_linear(DATA8 * output,int * points)87 _interpolate_linear(DATA8 *output, int *points)
88 {
89    DATA8 val = 0;
90    int j, k, last_idx = 0;
91    for (j = 0; j < 256; j++)
92      {
93         if (points[j] != -1)
94           {
95              output[j] = (DATA8) points[j];
96              for (k = last_idx + 1; k < j; k++)
97                output[k] = (DATA8) (points[j] + ((k - last_idx) * (points[j] - points[last_idx]) / (j - last_idx)));
98              last_idx = j;
99           }
100      }
101    val = (DATA8) points[last_idx];
102    for (j = last_idx + 1; j < 256; j++)
103      output[j] = val;
104    return EINA_TRUE;
105 }
106 
107 Eina_Bool
evas_filter_interpolate(DATA8 * output,int * points,Evas_Filter_Interpolation_Mode mode)108 evas_filter_interpolate(DATA8 *output, int *points,
109                         Evas_Filter_Interpolation_Mode mode)
110 {
111    switch (mode)
112      {
113       case EVAS_FILTER_INTERPOLATION_MODE_NONE:
114         return _interpolate_none(output, points);
115       case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
116       default:
117         return _interpolate_linear(output, points);
118      }
119 }
120 
121 int
evas_filter_smallest_pow2_larger_than(int val)122 evas_filter_smallest_pow2_larger_than(int val)
123 {
124    int n;
125 
126    for (n = 0; n < 32; n++)
127      if (val <= (1 << n)) return n;
128 
129    ERR("Value %d is too damn high!", val);
130    return 32;
131 }
132