/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- newSWFGradient
- SWFGradient_setSpreadMode
- SWFGradient_setInterpolationMode
- SWFGradient_setFocalPoint
- SWFGradient_isFocalGradient
- destroySWFGradient
- SWFGradient_addEntry
- SWFOutput_writeGradientAsFilter
- SWFGradientMatrix_update
- SWFOutput_writeGradient
- SWFOutput_writeMorphGradient
/*
Ming, an SWF output library
Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
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: gradient.c,v 1.23 2009/05/20 10:05:59 strk Exp $ */
#include <stdlib.h>
#include <math.h>
#include "libming.h"
#include "matrix.h"
#include "gradient.h"
#include "libming.h"
struct gradientEntry
{
byte ratio;
byte r;
byte g;
byte b;
byte a;
};
struct SWFGradient_s
{
int spreadMode;
int interpolationMode;
struct gradientEntry entries[15];
int nGrads;
float focalPoint;
int isFocalGradient;
};
SWFGradient
newSWFGradient()
{
SWFGradient gradient = (SWFGradient) malloc(sizeof(struct SWFGradient_s));
gradient->spreadMode = 0;
gradient->interpolationMode = 0;
gradient->nGrads = 0;
gradient->isFocalGradient = 0;
return gradient;
}
/*
* set gradient spread mode
* SWF8 allows to set different spread modes:
* SWF_GRADIENT_PAD (default)
* SWF_GRADIENT_REFLECT
* SWF_GRADIENT_REPEAT
*/
void SWFGradient_setSpreadMode(SWFGradient gradient, GradientSpreadMode mode)
{
gradient->spreadMode = mode;
}
/*
* set gradient interpolation mode
* SWF8 allows to set different interpolation modes:
* SWF_GRADIENT_NORMAL (default)
* SWF_GRADIENT_LINEAR
*/
void SWFGradient_setInterpolationMode(SWFGradient gradient, GradientInterpolationMode mode)
{
gradient->interpolationMode = mode;
}
/*
* creates a radial gradient with focal point
* valid focalPoint value range is -1.0 ... 1.0
* where -1.0 means the focal point is close to the left border of
* the radial gradient circle; 0.0 is in the center and 1.0 is close
* to the right border.
*/
void SWFGradient_setFocalPoint(SWFGradient gradient, float focalPoint)
{
gradient->isFocalGradient = 1;
if(focalPoint < -1.0) focalPoint = -1.0;
if(focalPoint > 1.0) focalPoint = 1.0;
gradient->focalPoint = focalPoint;
}
int SWFGradient_isFocalGradient(SWFGradient gradient)
{
return gradient->isFocalGradient;
}
void
destroySWFGradient(SWFGradient gradient)
{
free(gradient);
}
/*
* add a gradient control point
* The ratio defines the position of the control point
* and RGBA defines its color.
* SWF <= 7 allows up to 8 control points
* SWF >= 8 allows up to 15 control points
*
* The ration parameter is a float and must be in a range
* between [0.0 ... 1.0].
*
* In order to use SWF8 gradient features you need to set
* SWFShapes version to SWF_SHAPE4. Use SWFShape_useVersion()
* and friends.
*/
void
SWFGradient_addEntry(SWFGradient gradient,
float ratio, byte r, byte g, byte b, byte a)
{
int nGrads = gradient->nGrads;
if ( nGrads == 15 )
return;
gradient->entries[nGrads].ratio = (byte)floor(255*ratio);
gradient->entries[nGrads].r = r;
gradient->entries[nGrads].g = g;
gradient->entries[nGrads].b = b;
gradient->entries[nGrads].a = a;
++gradient->nGrads;
}
void
SWFOutput_writeGradientAsFilter(SWFOutput out, SWFGradient gradient)
{
int i;
int nGrads = gradient->nGrads;
if(nGrads > 8)
{
SWF_warn("Can't write more than 8 control points for filter gradients\n");
nGrads = 8;
}
SWFOutput_writeUInt8(out, nGrads); /* only 1-8 allowed */
for ( i=0; i<nGrads; ++i )
{
SWFOutput_writeUInt8(out, gradient->entries[i].r);
SWFOutput_writeUInt8(out, gradient->entries[i].g);
SWFOutput_writeUInt8(out, gradient->entries[i].b);
SWFOutput_writeUInt8(out, gradient->entries[i].a);
}
for ( i=0; i<nGrads; ++i )
SWFOutput_writeUInt8(out, gradient->entries[i].ratio);
}
#define GRADIENT_SIZE 32768.0
void
SWFGradientMatrix_update(SWFMatrix matrix, SWFRect bounds)
{
int w, h;
float scaleX, scaleY;
SWFMatrix tmp;
if(bounds == NULL)
return;
w = SWFRect_getWidth(bounds);
h = SWFRect_getHeight(bounds);
scaleX = w / GRADIENT_SIZE;
scaleY = h / GRADIENT_SIZE;
/* update matrix translation first, to be realtive to the gradient's
* coordinate system. */
SWFMatrix_moveTo(matrix, SWFMatrix_getTranslateX(matrix) / scaleX,
SWFMatrix_getTranslateY(matrix) / scaleY);
tmp = newSWFMatrix(scaleX, 0, 0, scaleY, bounds->minX + w/2, bounds->minY + h/2);
/* temporary matrix scales gradient to given bounds and centers it. */
/* all transformations done by the user are "applied" on the tmp matrix */
/* matrix = matrix * tmp -> "matrix is followed by tmp" */
SWFMatrix_multiply(matrix, tmp);
destroySWFMatrix(tmp);
}
void
SWFOutput_writeGradient(SWFOutput out, SWFGradient gradient, SWFBlocktype shapeType)
{
int i;
int nGrads = gradient->nGrads;
if(shapeType == SWF_DEFINESHAPE4)
{
byte flags ;
nGrads = min(nGrads, 15);
flags = nGrads;
flags |= (0x3 & gradient->interpolationMode) << 4;
flags |= (0x3 & gradient->spreadMode) << 6;
SWFOutput_writeUInt8(out, flags); /* only 1-15 allowed */
}
else
{
nGrads = min(nGrads, 8);
SWFOutput_writeUInt8(out, nGrads); /* only 1-8 allowed */
}
for ( i=0; i<nGrads; ++i )
{
SWFOutput_writeUInt8(out, gradient->entries[i].ratio);
SWFOutput_writeUInt8(out, gradient->entries[i].r);
SWFOutput_writeUInt8(out, gradient->entries[i].g);
SWFOutput_writeUInt8(out, gradient->entries[i].b);
if ( shapeType >= SWF_DEFINESHAPE3 )
SWFOutput_writeUInt8(out, gradient->entries[i].a);
}
if(shapeType == SWF_DEFINESHAPE4 && gradient->isFocalGradient)
SWFOutput_writeFixed8(out, gradient->focalPoint);
}
void
SWFOutput_writeMorphGradient(SWFOutput out,
SWFGradient gradient1, SWFGradient gradient2)
{
int i;
int nGrads = min(min(gradient1->nGrads, gradient2->nGrads), 8);
SWFOutput_writeUInt8(out, nGrads); /* only 1-8 allowed */
for ( i=0; i<nGrads; ++i )
{
SWFOutput_writeUInt8(out, gradient1->entries[i].ratio);
SWFOutput_writeUInt8(out, gradient1->entries[i].r);
SWFOutput_writeUInt8(out, gradient1->entries[i].g);
SWFOutput_writeUInt8(out, gradient1->entries[i].b);
SWFOutput_writeUInt8(out, gradient1->entries[i].a);
SWFOutput_writeUInt8(out, gradient2->entries[i].ratio);
SWFOutput_writeUInt8(out, gradient2->entries[i].r);
SWFOutput_writeUInt8(out, gradient2->entries[i].g);
SWFOutput_writeUInt8(out, gradient2->entries[i].b);
SWFOutput_writeUInt8(out, gradient2->entries[i].a);
}
}
/*
* Local variables:
* tab-width: 2
* c-basic-offset: 2
* End:
*/