root/src/blocks/filter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. newSWFShadow
  2. destroySWFShadow
  3. newSWFBlur
  4. destroySWFBlur
  5. newSWFFilterMatrix
  6. destroySWFFilterMatrix
  7. writeDropShadowFilter
  8. writeBlurFilter
  9. writeGlowFilter
  10. writeBevelFilter
  11. writeGradientGlowFilter
  12. writeConvolutionFilter
  13. writeColorMatrixFilter
  14. writeGradientBevelFilter
  15. SWFOutput_writeSWFFilter
  16. destroySWFFilter
  17. newColorMatrixFilter
  18. newConvolutionFilter
  19. newGradientBevelFilter
  20. newGradientGlowFilter
  21. newBevelFilter
  22. newGlowFilter
  23. newBlurFilter
  24. newDropShadowFilter
  25. newSWFFilterList
  26. SWFFilterList_add
  27. SWFOutput_writeFilterList
  28. destroySWFFilterList

/*
    Ming, an SWF output library
    Copyright (C) 2008 Klaus Rechert

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* $Id: filter.c,v 1.8 2008/09/28 16:53:59 krechert Exp $ */

#ifndef __C2MAN__
#include <stdlib.h>
#include <string.h>
#endif

#include "gradient.h"
#include "output.h"
#include "filter.h"
#include "error.h"

#include "libming.h"


struct Shadow_s
{
        float   angle;
        float   distance;
        float   strength;
};


/*
 * create a new SWFShadow (contructor)
 * This Function creates a new SWFShadow object. Only useful for creating 
 * SWFFilter objects.
 */
SWFShadow 
newSWFShadow(float angle /* angle in radians */, 
             float distance /* distance in px*/, 
             float strength /* strength */)
{
        SWFShadow shadow = (SWFShadow)malloc(sizeof(struct Shadow_s));
        
        shadow->angle = angle;
        shadow->distance = distance;
        shadow->strength = strength;

        return shadow;
}

void destroySWFShadow(SWFShadow s)
{
        free(s);
}

struct Blur_s
{
        float   blurX;
        float   blurY;
        int     passes;
};


/*
 * create a new SWFBlur
 * This function creates a new SWFBlur object. Only useful for creating
 * SWFFilter objects
 */
SWFBlur 
newSWFBlur(float blurX /* horiz. blur amount */, 
           float blurY /* vert. blur amount */, 
           int passes /* number of passes. shoub be <= 3 */)
{
        SWFBlur blur = (SWFBlur)malloc(sizeof(struct Blur_s));

        blur->blurX = blurX;
        blur->blurY = blurY;
        blur->passes = passes;

        return blur;
}

void destroySWFBlur(SWFBlur b)
{
        free(b);
}

struct BlurFilter
{
        SWFBlur blur;
};

struct DropShadowFilter
{
        SWFColor                color;  
        SWFBlur                 blur;
        SWFShadow               shadow; 
        int                     flags;
};

struct GlowFilter
{
        SWFColor        color;
        SWFBlur         blur;
        float           strength;
        int             flags;
};

struct BevelFilter
{
        SWFColor        shadowColor;
        SWFColor        highlightColor;
        SWFBlur         blur;
        SWFShadow       shadow;
        int             flags;
};

struct GradientGlowFilter
{
        SWFGradient     gradient;
        SWFBlur         blur;   
        SWFShadow       shadow;
        int             flags;  
};

struct GradientBevelFilter
{
        SWFGradient     gradient;
        SWFBlur         blur;
        SWFShadow       shadow; 
        int             flags;
};


struct FilterMatrix_s
{
        int cols;
        int rows;
        float *values;
};

/*
 * create a new FilterMatrix (constructor)
 * This function creates a new SFWFilterMatrix. Only useful 
 * for creating SWFFilter objects.
 */
SWFFilterMatrix 
newSWFFilterMatrix(int cols /* number of cols */, 
                   int rows /* number of rows */, 
                   float *vals /* vals[cols * rows]. Will be copied */)
{
        SWFFilterMatrix matrix;

        if(cols <= 0 || rows <= 0)
                return NULL;
        
        matrix = (SWFFilterMatrix)malloc(sizeof(struct FilterMatrix_s));

        matrix->cols = cols;
        matrix->rows = rows;

        matrix->values = (float *)malloc(cols * rows * sizeof(float));
        memcpy(matrix->values, vals, cols * rows * sizeof(float));

        return matrix;
}

void destroySWFFilterMatrix(SWFFilterMatrix m)
{
        if(m == NULL)
                return;

        free(m->values);
        free(m);
}

struct ConvolutionFilter
{
        SWFFilterMatrix matrix;
        float           divisor;
        float           bias;
        SWFColor        color;
        int             flags;
};


struct ColorMatrixFilter
{
        SWFFilterMatrix matrix;
};

struct SWFFilter_s
{
        int id;
        union {
                struct DropShadowFilter         dropShadow;
                struct BlurFilter               blur;
                struct GlowFilter               glow;
                struct BevelFilter              bevel;
                struct GradientGlowFilter       gradientGlow;
                struct ConvolutionFilter        convolution;
                struct ColorMatrixFilter        colorMatrix;
                struct GradientBevelFilter      gradientBevel;
        } filter;
};

static void writeDropShadowFilter(SWFOutput out, struct DropShadowFilter *filter)
{
        int flags = FILTER_MODE_COMPOSITE;

        SWFOutput_writeUInt8(out, filter->color.red);
        SWFOutput_writeUInt8(out, filter->color.green);
        SWFOutput_writeUInt8(out, filter->color.blue);
        SWFOutput_writeUInt8(out, filter->color.alpha);
        
        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 

        SWFOutput_writeFixed(out, filter->shadow->angle);
        SWFOutput_writeFixed(out, filter->shadow->distance);
        SWFOutput_writeFixed8(out, filter->shadow->strength);

        flags |= filter->flags;
        flags |= (0x1F & filter->blur->passes);
        SWFOutput_writeUInt8(out, flags);
}

static void writeBlurFilter(SWFOutput out, struct BlurFilter *filter)
{
        int flags = 0;

        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 

        flags = 0xff & (filter->blur->passes << 3);
        SWFOutput_writeUInt8(out, flags);
}

static void writeGlowFilter(SWFOutput out, struct GlowFilter *filter)
{
        int flags = FILTER_MODE_COMPOSITE;

        SWFOutput_writeUInt8(out, filter->color.red);
        SWFOutput_writeUInt8(out, filter->color.green);
        SWFOutput_writeUInt8(out, filter->color.blue);
        SWFOutput_writeUInt8(out, filter->color.alpha);

        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 

        SWFOutput_writeFixed8(out, filter->strength);
        flags |= filter->flags;
        flags |= (0x1F & filter->blur->passes);
        SWFOutput_writeUInt8(out, flags);
}

static void writeBevelFilter(SWFOutput out, struct BevelFilter *filter)
{
        int flags = FILTER_MODE_COMPOSITE;

        SWFOutput_writeUInt8(out, filter->shadowColor.red);
        SWFOutput_writeUInt8(out, filter->shadowColor.green);
        SWFOutput_writeUInt8(out, filter->shadowColor.blue);
        SWFOutput_writeUInt8(out, filter->shadowColor.alpha);

        SWFOutput_writeUInt8(out, filter->highlightColor.red);
        SWFOutput_writeUInt8(out, filter->highlightColor.green);
        SWFOutput_writeUInt8(out, filter->highlightColor.blue);
        SWFOutput_writeUInt8(out, filter->highlightColor.alpha);

        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 
        
        SWFOutput_writeFixed(out, filter->shadow->angle);
        SWFOutput_writeFixed(out, filter->shadow->distance);
        SWFOutput_writeFixed8(out, filter->shadow->strength);

        flags |= filter->flags;
        flags |= (0xF & filter->blur->passes);
        SWFOutput_writeUInt8(out, flags);
}

static void writeGradientGlowFilter(SWFOutput out, struct GradientGlowFilter *filter)
{
        int flags = FILTER_MODE_COMPOSITE;

        SWFOutput_writeGradientAsFilter(out, filter->gradient);
        
        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 
        
        SWFOutput_writeFixed(out, filter->shadow->angle);
        SWFOutput_writeFixed(out, filter->shadow->distance);
        SWFOutput_writeFixed8(out, filter->shadow->strength);

        flags |= filter->flags;
        flags |= (0xF & filter->blur->passes);
        SWFOutput_writeUInt8(out, flags);
}

static void writeConvolutionFilter(SWFOutput out, struct ConvolutionFilter *filter)
{
        int i;

        SWFOutput_writeUInt8(out, filter->matrix->cols);
        SWFOutput_writeUInt8(out, filter->matrix->rows);

        SWFOutput_writeFloat(out, filter->divisor);
        SWFOutput_writeFloat(out, filter->bias);

        for(i = 0; i < filter->matrix->cols * filter->matrix->rows; i++)
                SWFOutput_writeFloat(out, filter->matrix->values[i]);

        SWFOutput_writeUInt8(out, filter->color.red);
        SWFOutput_writeUInt8(out, filter->color.green);
        SWFOutput_writeUInt8(out, filter->color.blue);
        SWFOutput_writeUInt8(out, filter->color.alpha);

        SWFOutput_writeUInt8(out, filter->flags);
}

static void writeColorMatrixFilter(SWFOutput out, struct ColorMatrixFilter *filter)
{
        int i;

        for(i = 0; i < filter->matrix->rows * filter->matrix->cols; i++)
                SWFOutput_writeFloat(out, filter->matrix->values[i]);
}

static void writeGradientBevelFilter(SWFOutput out, struct GradientBevelFilter *filter)
{
        int flags = FILTER_MODE_COMPOSITE;

        SWFOutput_writeGradientAsFilter(out, filter->gradient);
        
        SWFOutput_writeFixed(out, filter->blur->blurX);
        SWFOutput_writeFixed(out, filter->blur->blurY); 
        
        SWFOutput_writeFixed(out, filter->shadow->angle);
        SWFOutput_writeFixed(out, filter->shadow->distance);
        SWFOutput_writeFixed8(out, filter->shadow->strength);

        flags |= filter->flags;
        flags |= (0xF & filter->blur->passes);
        SWFOutput_writeUInt8(out, flags);
}

void 
SWFOutput_writeSWFFilter(SWFOutput out, SWFFilter filter)
{
        if(out == NULL || filter == NULL)
                return;

        SWFOutput_writeUInt8(out, filter->id);
        switch(filter->id)
        {
                case SWFFILTER_TYPE_DROPSHADOW:
                        writeDropShadowFilter(out, &filter->filter.dropShadow);
                        break;
                case SWFFILTER_TYPE_BLUR:
                        writeBlurFilter(out, &filter->filter.blur);
                        break;
                case SWFFILTER_TYPE_GLOW:
                        writeGlowFilter(out, &filter->filter.glow);
                        break;
                case SWFFILTER_TYPE_BEVEL:
                        writeBevelFilter(out, &filter->filter.bevel);
                        break;
                case SWFFILTER_TYPE_GRADIENTGLOW:
                        writeGradientGlowFilter(out, &filter->filter.gradientGlow);
                        break;
                case SWFFILTER_TYPE_CONVOLUTION:
                        writeConvolutionFilter(out, &filter->filter.convolution);
                        break;
                case SWFFILTER_TYPE_COLORMATRIX:
                        writeColorMatrixFilter(out, &filter->filter.colorMatrix);
                        break;
                case SWFFILTER_TYPE_GRADIENTBEVEL:
                        writeGradientBevelFilter(out, &filter->filter.gradientBevel);
                        break;
                default:
                        SWF_error("destroySWFFilter: invalid filter\n");
        }
        
}

void 
destroySWFFilter(SWFFilter filter)
{
        if(filter == NULL)
                return;

        switch(filter->id)
        {
                case SWFFILTER_TYPE_DROPSHADOW:
                        // destroyDropShadowFilter(&filter->filter.dropShadow);
                        break;
                case SWFFILTER_TYPE_BLUR:
                        // destroyBlurFilter(&filter->filter.blur);
                        break;
                case SWFFILTER_TYPE_GLOW:
                        // destroyGlowFilter(&filter->filter.glow);
                        break;
                case SWFFILTER_TYPE_BEVEL:
                        //destroyBevelFilter(&filter->filter.bevel);
                        break;
                case SWFFILTER_TYPE_GRADIENTGLOW:
                        // destroyGradientGlowFilter(&filter->filter.gradientGlow);
                        break;
                case SWFFILTER_TYPE_CONVOLUTION:
                        // destroyConvolutionFilter(&filter->filter.convolution);
                        break;
                case SWFFILTER_TYPE_COLORMATRIX:
                        // destroyColorMatrixFilter(&filter->filter.colorMatrix);
                        break;
                case SWFFILTER_TYPE_GRADIENTBEVEL:
                        // destroyGradientBevelFilter(&filter->filter.gradientBevel);
                        break;
                default:
                        SWF_error("destroySWFFilter: invalid filter\n");
        }
        free(filter);
}

/* 
 * creates a new ColormatrixFilter 
 * Matrix has to be 5 x 4
 * [r0 ... r4]
 * [g0 ... g4]
 * [b0 ... b4]
 * [a0 ... a4]
 */
SWFFilter
newColorMatrixFilter(SWFFilterMatrix matrix /* matrix */)
{
        SWFFilter filter;

        if(matrix == NULL)
                return NULL;

        if(matrix->rows != 4 || matrix->cols != 5)
        {
                SWF_warn("newColorMatrixFilter: color matrix has to be 5x4\n");
                return NULL;
        }       

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_COLORMATRIX;

        filter->filter.colorMatrix.matrix = matrix;

        return filter;
}

/*
 * creates a new ConvolutionFilter
 */
SWFFilter 
newConvolutionFilter(SWFFilterMatrix matrix /* matrix */, 
                     float divisor /* divisor applied to matrix */,
                     float bias /* matrix bias */,
                     SWFColor color /* default color */,
                     int flags /* FILTER_FLAG_CLAMP , FILTER_FLAG_PRESERVE_ALPHA */)
{
        SWFFilter filter;
        struct ConvolutionFilter *convolution;

        if(matrix == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_CONVOLUTION;

        convolution = &filter->filter.convolution;

        convolution->matrix = matrix;
        convolution->divisor = divisor;
        convolution->bias = bias;
        convolution->color = color;
        convolution->flags = flags;

        return filter;
}
                     


/*
 * create a GradientBevelFilter 
 * This functions creates a gradient bevel filter. Extends BevelFilter by
 * using a gradient instead of a simple color
 */
SWFFilter
newGradientBevelFilter(SWFGradient gradient /* gradient */, 
                       SWFBlur blur /* blur */,
                       SWFShadow shadow /* shadow */,
                       int flags /* FILTER_MODE_INNER,  FILTER_MODE_KO, FILTER_MODE_ONTOP */)
{
        SWFFilter filter;
        struct GradientBevelFilter *gBevel;
        
        if(gradient == NULL || blur == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_GRADIENTBEVEL;

        gBevel = &filter->filter.gradientBevel;

        gBevel->gradient = gradient;
        gBevel->blur = blur;
        gBevel->shadow = shadow;
        gBevel->flags = flags;

        return filter;
} 

/* 
 * creates a GardientGlowFilter
 * This functions creates a gradient glow filter. Extends GlowFilter by
 * using a gradient instead of a simple color
 */
SWFFilter 
newGradientGlowFilter(SWFGradient gradient /* gradient */, 
                      SWFBlur blur /* blur */, 
                      SWFShadow shadow /* shadow */,
                      int flags /* FILTER_MODE_INNER,  FILTER_MODE_KO, FILTER_MODE_ONTOP */)
{
        SWFFilter filter;
        struct GradientGlowFilter *gGlow;

        if(gradient == NULL || blur == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_GRADIENTGLOW;

        gGlow = &filter->filter.gradientGlow;

        gGlow->gradient = gradient;
        gGlow->blur = blur;
        gGlow->shadow = shadow;
        gGlow->flags = flags;

        return filter;
}

/* 
 * creates a BevelFilter
 * This functions creates a bevel filter. Creates a smooth bevel
 */
SWFFilter 
newBevelFilter(SWFColor shadowColor /* shadow color */, 
               SWFColor highlightColor /* highlight color */, 
               SWFBlur blur /* blur */, 
               SWFShadow shadow /* shadow */,
               int flags /* FILTER_MODE_INNER,  FILTER_MODE_KO, FILTER_MODE_ONTOP */)
{
        SWFFilter filter;
        struct BevelFilter *bevel;

        if(blur == NULL || shadow == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_BEVEL;

        bevel = &filter->filter.bevel;

        bevel->shadowColor = shadowColor;
        bevel->highlightColor = highlightColor;
        bevel->blur = blur; 
        bevel->shadow = shadow;
        bevel->flags = flags;

        return filter;
}

/* 
 * creates a GlowFilter
 * This functions creates a glow filter.
 */
SWFFilter 
newGlowFilter(SWFColor color /* color of shadow */, 
              SWFBlur blur /* blur */, 
              float strength /* strength */, 
              int flags /* FILTER_MODE_INNER,  FILTER_MODE_KO */)
{
        SWFFilter filter;
        struct GlowFilter *glow;
        
        if(blur == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_GLOW;

        glow = &filter->filter.glow;

        glow->color = color;
        glow->blur = blur;
        glow->strength = strength;
        glow->flags = flags;

        return filter;
}

/*
 * creates a BlurFilter 
 * This functions creates a blur filter.
 */
SWFFilter 
newBlurFilter(SWFBlur blur /* blur */)
{
        SWFFilter filter;
        struct BlurFilter *b;
        if(blur == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_BLUR;
        b = &filter->filter.blur;
        b->blur = blur;

        return filter;
}

/*
 * creates a DropShadowFilter 
 * This functions creates a drop shadow filter filter.
 */
SWFFilter 
newDropShadowFilter(SWFColor color /* color of shadow */, 
                    SWFBlur blur /* blur */, 
                    SWFShadow shadow /* shadow */, 
                    int flags /* FILTER_MODE_INNER,  FILTER_MODE_KO */)
{
        struct DropShadowFilter *dropShadow;
        SWFFilter filter;

        if(blur == NULL || shadow == NULL)
                return NULL;

        filter = (SWFFilter)malloc(sizeof(struct SWFFilter_s));
        filter->id = SWFFILTER_TYPE_DROPSHADOW;

        dropShadow = &filter->filter.dropShadow;
        dropShadow->color = color;
        dropShadow->blur = blur;
        dropShadow->shadow = shadow;
        dropShadow->flags = flags;

        return filter;
}

SWFFilterList newSWFFilterList()
{
        SWFFilterList list;

        list = (SWFFilterList)malloc(sizeof(struct SWFFilterList_s));
        list->numFilter = 0;
        list->filter = NULL;
        return list;
}

void SWFFilterList_add(SWFFilterList list, SWFFilter filter)
{
        int count = list->numFilter;
        list->filter = (SWFFilter*)realloc(list->filter, (count + 1) * sizeof(SWFFilter));
        list->filter[count] = filter;
        list->numFilter++;
}

void SWFOutput_writeFilterList(SWFOutput out, SWFFilterList list)
{
        int i;
        if(list->numFilter <= 0)
                return;

        SWFOutput_writeUInt8(out, list->numFilter);
        for(i = 0; i < list->numFilter; i++)
                SWFOutput_writeSWFFilter(out, list->filter[i]);
}

void destroySWFFilterList(SWFFilterList list)
{
        free(list->filter);
        free(list);
}

/* [<][>][^][v][top][bottom][index][help] */