summaryrefslogblamecommitdiff
path: root/src/lib/evas/filters/evas_filter_utils.c
blob: 1e27895161886653ca170c4d6e58d3b9d5e92c6e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                         





                                                       
                                                     

                          

                               




                                                          







                                                                       


                                                                     
                                                         

                







                                                              


                    
                      
      




                                                            
                                                   
                                                          

            













                                                                 

           
       










                                                                     


             












































                                                                    







                                                                      




                                                                











                                              
/* Utility functions for the filters.  */

#include "evas_filter_private.h"

Evas_Filter_Buffer *
evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
                              Evas_Filter_Buffer *src,
                              unsigned w, unsigned h)
{
   Evas_Filter_Buffer *fb;
   Image_Entry *dstdata = NULL;
   Image_Entry *srcdata;
   void *drawctx;

   srcdata = evas_filter_buffer_backing_get(ctx, src->id);
   EINA_SAFETY_ON_NULL_RETURN_VAL(srcdata, NULL);

   if (src->alpha_only)
     {
        // There is no supporting function in Evas for alpha scaling...
        // but guess what? There is also no use case in the filters :)
        CRI("Alpha buffer scaling is not supported");
        return NULL;
     }

   fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
   if (!fb) return NULL;

   dstdata = evas_filter_buffer_backing_get(ctx, fb->id);
   if (!dstdata)
     {
        CRI("No backing found for buffer %d", fb->id);
        return NULL;
     }

   if ((dstdata->w != w) || (dstdata->h != h))
     {
        CRI("Buffer size mismatch: got %dx%d requested %dx%d",
            dstdata->w, dstdata->h, w, h);
        return NULL;
     }

   if (ctx->gl_engine)
     {
        RGBA_Image *s = (RGBA_Image *) srcdata;
        RGBA_Image *d = (RGBA_Image *) dstdata;
        EINA_SAFETY_ON_NULL_RETURN_VAL(s->image.data, NULL);
        EINA_SAFETY_ON_NULL_RETURN_VAL(d->image.data, NULL);

        if (src->w == (int) w && src->h == (int) h)
          memcpy(d->image.data, s->image.data, w * h * 4);
        else
          {
             Eina_Bool ok;
             RGBA_Draw_Context dc;

             memset(&dc, 0, sizeof(dc));
             dc.sli.h = 1;
             dc.render_op = EVAS_RENDER_COPY;

             ok = evas_common_scale_rgba_in_to_out_clip_sample
                   (s, d, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
             if (!ok)
               {
                  ERR("RGBA Image scaling failed.");
                  return NULL;
               }
          }
     }
   else
     {
        drawctx = ENFN->context_new(ENDT);
        ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
        ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY);
        ENFN->image_draw(ENDT, drawctx, dstdata, srcdata,
                         0, 0, src->w, src->h, // src
                         0, 0, w, h, // dst
                         EINA_TRUE, // smooth
                         EINA_FALSE); // Not async
        ENFN->context_free(ENDT, drawctx);
     }

   return fb;
}

static Eina_Bool
_interpolate_none(DATA8 *output, DATA8 *points, int point_count)
{
   int j, k, val, x1, x2;
   for (j = 0; j < point_count; j++)
     {
        x1 = points[j * 2];
        val = points[j * 2 + 1];
        if (j < (point_count - 1))
          x2 = points[(j + 1) * 2];
        else
          x2 = 256;
        if (x2 < x1) return EINA_FALSE;
        for (k = x1; k < x2; k++)
          output[k] = val;
     }
   return EINA_TRUE;
}

static Eina_Bool
_interpolate_linear(DATA8 *output, DATA8 *points, int point_count)
{
   int j, k, val1, val2, x1, x2;
   for (j = 0; j < point_count; j++)
     {
        x1 = points[j * 2];
        val1 = points[j * 2 + 1];
        if (j < (point_count - 1))
          {
             x2 = points[(j + 1) * 2];
             val2 = points[(j + 1) * 2 + 1];
          }
        else
          {
             x2 = 256;
             val2 = val1;
          }
        if (x2 < x1) return EINA_FALSE;
        for (k = x1; k < x2; k++)
          output[k] = val1 + ((val2 - val1) * (k - x1)) / (x2 - x1);
     }
   return EINA_TRUE;
}

Eina_Bool
evas_filter_interpolate(DATA8 *output, DATA8 *points, int point_count,
                        Evas_Filter_Interpolation_Mode mode)
{
   switch (mode)
     {
      case EVAS_FILTER_INTERPOLATION_MODE_NONE:
        return _interpolate_none(output, points, point_count);
      case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
      default:
        return _interpolate_linear(output, points, point_count);
     }
}

int
evas_filter_smallest_pow2_larger_than(int val)
{
   int n;

   for (n = 0; n < 32; n++)
     if (val <= (1 << n)) return n;

   ERR("Value %d is too damn high!", val);
   return 32;
}