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

                                






                                                                      



                                    
                                 

                                            












                                                                                                  

                                                            


                                                                      


















                                      





                                     
                                                               





                                       
                                   


                                       
                                     



                                   
              
















                                                                     
#include "evas_filter_private.h"

/* Apply geomeetrical transformations to a buffer.
 * This filter is a bit simplistic at the moment.
 *
 * It also assumes the destination is empty, as it does not use blend
 * operations. This should probably be fixed later on (use evas_map?).
 */

static Eina_Bool
_vflip_cpu(Evas_Filter_Command *cmd)
{
   size_t datasize, stride;
   DATA8 *in, *out, *span = NULL;
   int w, h, sy, dy, oy, center, t, b, objh;
   int s0, s1, d0, d1;

   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, EINA_FALSE);
   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, EINA_FALSE);
   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);

   w = cmd->input->w;
   h = cmd->input->h;
   EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->w == w, EINA_FALSE);
   EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->h == h, EINA_FALSE);
   EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->alpha_only == cmd->input->alpha_only, EINA_FALSE);

   in = ((RGBA_Image *) cmd->input->backing)->image.data8;
   out = ((RGBA_Image *) cmd->output->backing)->image.data8;
   datasize = cmd->input->alpha_only ? sizeof(DATA8) : sizeof(DATA32);
   stride = w * datasize;

   oy = cmd->draw.oy;
   t = cmd->ctx->padt;
   b = cmd->ctx->padb;
   objh = h - t - b;
   center = t + objh / 2 + oy;

   s0 = t;
   s1 = h - b - 1;
   if (oy >= 0)
     {
        d0 = center + (objh / 2) + oy;
        d1 = center - (objh / 2) - oy;
     }
   else
     {
        d0 = center + (objh / 2) - oy;
        d1 = center - (objh / 2) + oy;
     }

   if (in == out)
     {
        span = malloc(stride);
        if (!span) return EINA_FALSE;
     }

   for (sy = s0, dy = d0; (dy >= d1) && (sy <= s1); sy++, dy--)
     {
        DATA8* src = in + stride * sy;
        DATA8* dst = out + stride * dy;

        if (in == out)
          {
             if (src == dst) break;
             memcpy(span, dst, stride);
             memcpy(dst, src, stride);
             memcpy(src, span, stride);
             if (sy >= center) break;
          }
        else
          memcpy(dst, src, stride);
     }
   free(span);
   return EINA_TRUE;
}

Evas_Filter_Apply_Func
evas_filter_transform_cpu_func_get(Evas_Filter_Command *cmd)
{
   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);

   switch (cmd->transform.flags)
     {
      case EVAS_FILTER_TRANSFORM_VFLIP:
        return _vflip_cpu;
      default:
        CRI("Unknown transform flag %d", (int) cmd->transform.flags);
        return NULL;
     }
}