Bug 363909 - Implement ColorMatrix filter. Patch by malex@cs.utexas.edu and longsonr r=tor,sr=roc

This commit is contained in:
longsonr%gmail.com 2007-02-20 11:03:00 +00:00
Родитель a1c35a6ac4
Коммит a63308f703
6 изменённых файлов: 352 добавлений и 3 удалений

Просмотреть файл

@ -857,6 +857,7 @@ GK_ATOM(usemap, "usemap")
GK_ATOM(validate, "validate")
GK_ATOM(valign, "valign")
GK_ATOM(value, "value")
GK_ATOM(values, "values")
GK_ATOM(valueOf, "value-of")
GK_ATOM(valuetype, "valuetype")
GK_ATOM(var, "var")
@ -994,6 +995,7 @@ GK_ATOM(grad, "grad")
GK_ATOM(gradientTransform, "gradientTransform")
GK_ATOM(gradientUnits, "gradientUnits")
GK_ATOM(hkern, "hkern")
GK_ATOM(hueRotate, "hueRotate")
GK_ATOM(identity, "identity")
GK_ATOM(image_rendering, "image-rendering")
GK_ATOM(in, "in")
@ -1009,6 +1011,7 @@ GK_ATOM(lighten, "lighten")
GK_ATOM(linear, "linear")
GK_ATOM(linearGradient, "linearGradient")
GK_ATOM(linearRGB, "linearRGB")
GK_ATOM(luminanceToAlpha, "luminanceToAlpha")
GK_ATOM(magnify, "magnify")
GK_ATOM(marker, "marker")
GK_ATOM(marker_end, "marker-end")
@ -1069,6 +1072,7 @@ GK_ATOM(requiredFeatures, "requiredFeatures")
GK_ATOM(rotate, "rotate")
GK_ATOM(rx, "rx")
GK_ATOM(ry, "ry")
GK_ATOM(saturate, "saturate")
GK_ATOM(scale, "scale")
GK_ATOM(set, "set")
GK_ATOM(seed, "seed")

Просмотреть файл

@ -109,6 +109,8 @@ NS_NewSVGFilterElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEBlendElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEColorMatrixElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEComponentTransferElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFECompositeElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
@ -220,6 +222,8 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
return NS_NewSVGFilterElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feBlend)
return NS_NewSVGFEBlendElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feColorMatrix)
return NS_NewSVGFEColorMatrixElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feComponentTransfer)
return NS_NewSVGFEComponentTransferElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feComposite)
@ -246,8 +250,7 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
return NS_NewSVGFEFloodElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feTurbulence)
return NS_NewSVGFETurbulenceElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feColorMatrix ||
name == nsGkAtoms::feConvolveMatrix ||
if (name == nsGkAtoms::feConvolveMatrix ||
name == nsGkAtoms::feDiffuseLighting ||
name == nsGkAtoms::feDisplacementMap ||
name == nsGkAtoms::feImage ||

Просмотреть файл

@ -983,6 +983,324 @@ nsSVGFEBlendElement::GetRequirements(PRUint32 *aRequirements)
return NS_OK;
}
//---------------------Color Matrix------------------------
typedef nsSVGFE nsSVGFEColorMatrixElementBase;
class nsSVGFEColorMatrixElement : public nsSVGFEColorMatrixElementBase,
public nsIDOMSVGFEColorMatrixElement,
public nsISVGFilter
{
protected:
friend nsresult NS_NewSVGFEColorMatrixElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGFEColorMatrixElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
// FE Base
NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEColorMatrixElementBase::)
// nsISVGFilter
NS_IMETHOD Filter(nsSVGFilterInstance *instance);
NS_IMETHOD GetRequirements(PRUint32 *aRequirements);
// Color Matrix
NS_DECL_NSIDOMSVGFECOLORMATRIXELEMENT
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEColorMatrixElementBase::)
NS_FORWARD_NSIDOMNODE(nsSVGFEColorMatrixElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGFEColorMatrixElementBase::)
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
//virtual NumberAttributesInfo GetNumberInfo();
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mType;
nsCOMPtr<nsIDOMSVGAnimatedNumberList> mValues;
nsCOMPtr<nsIDOMSVGAnimatedString> mIn1;
};
NS_IMPL_NS_NEW_SVG_ELEMENT(FEColorMatrix)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGFEColorMatrixElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEColorMatrixElement)
NS_INTERFACE_MAP_ENTRY(nsISVGFilter)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEColorMatrixElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGFEColorMatrixElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGFEColorMatrixElement::nsSVGFEColorMatrixElement(nsINodeInfo *aNodeInfo)
: nsSVGFEColorMatrixElementBase(aNodeInfo)
{
}
nsresult
nsSVGFEColorMatrixElement::Init()
{
nsresult rv = nsSVGFEColorMatrixElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
static struct nsSVGEnumMapping gTypes[] = {
{&nsGkAtoms::matrix, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX},
{&nsGkAtoms::saturate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE},
{&nsGkAtoms::hueRotate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE},
{&nsGkAtoms::luminanceToAlpha, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA},
{nsnull, 0}
};
// Create mapped properties:
// DOM property: type, #IMPLIED attrib: type
{
nsCOMPtr<nsISVGEnum> types;
rv = NS_NewSVGEnum(getter_AddRefs(types),
nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX,
gTypes);
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mType), types);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::type, mType);
NS_ENSURE_SUCCESS(rv,rv);
}
// DOM property: values, #IMPLIED attrib: values
{
nsCOMPtr<nsIDOMSVGNumberList> values;
rv = NS_NewSVGNumberList(getter_AddRefs(values));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mValues), values);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::values, mValues);
NS_ENSURE_SUCCESS(rv,rv);
}
// DOM property: in1 , #IMPLIED attrib: in
{
rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1));
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::in, mIn1);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEColorMatrixElement)
//----------------------------------------------------------------------
// nsSVGFEColorMatrixElement methods
/* readonly attribute nsIDOMSVGAnimatedString in1; */
NS_IMETHODIMP nsSVGFEColorMatrixElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
{
*aIn = mIn1;
NS_IF_ADDREF(*aIn);
return NS_OK;
}
/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
NS_IMETHODIMP nsSVGFEColorMatrixElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
{
*aType = mType;
NS_IF_ADDREF(*aType);
return NS_OK;
}
/* readonly attribute nsIDOMSVGAnimatedNumberList values; */
NS_IMETHODIMP nsSVGFEColorMatrixElement::GetValues(nsIDOMSVGAnimatedNumberList * *aValues)
{
*aValues = mValues;
NS_IF_ADDREF(*aValues);
return NS_OK;
}
NS_IMETHODIMP
nsSVGFEColorMatrixElement::GetRequirements(PRUint32 *aRequirements)
{
*aRequirements = CheckStandardNames(mIn1);
return NS_OK;
}
//----------------------------------------------------------------------
// nsSVGElement methods
NS_IMETHODIMP
nsSVGFEColorMatrixElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::UNPREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData);
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 type;
mType->GetAnimVal(&type);
nsCOMPtr<nsIDOMSVGNumberList> list;
mValues->GetAnimVal(getter_AddRefs(list));
PRUint32 num = 0;
if (list) {
list->GetNumberOfItems(&num);
}
nsRect rect = fr.GetRect();
PRInt32 stride = fr.GetDataStride();
#ifdef DEBUG_tor
fprintf(stderr, "FILTER COLOR MATRIX rect: %d,%d %dx%d\n",
rect.x, rect.y, rect.width, rect.height);
#endif
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::values) &&
(type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX ||
type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE ||
type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE)) {
// identity matrix filter
fr.CopySourceImage();
return NS_OK;
}
static const float identityMatrix[] =
{ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0 };
static const float luminanceToAlphaMatrix[] =
{ 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0.2125f, 0.7154f, 0.0721f, 0, 0 };
nsCOMPtr<nsIDOMSVGNumber> number;
float colorMatrix[20];
float s, c;
switch (type) {
case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX:
if (num != 20)
return NS_ERROR_FAILURE;
for(PRUint32 j = 0; j < num; j++) {
list->GetItem(j, getter_AddRefs(number));
number->GetValue(&colorMatrix[j]);
}
break;
case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE:
if (num != 1)
return NS_ERROR_FAILURE;
list->GetItem(0, getter_AddRefs(number));
number->GetValue(&s);
if (s > 1 || s < 0)
return NS_ERROR_FAILURE;
memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
colorMatrix[0] = 0.213f + 0.787f * s;
colorMatrix[1] = 0.715f - 0.715f * s;
colorMatrix[2] = 0.072f - 0.072f * s;
colorMatrix[5] = 0.213f - 0.213f * s;
colorMatrix[6] = 0.715f + 0.285f * s;
colorMatrix[7] = 0.072f - 0.072f * s;
colorMatrix[10] = 0.213f - 0.213f * s;
colorMatrix[11] = 0.715f - 0.715f * s;
colorMatrix[12] = 0.715f - 0.715f * s;
break;
case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE:
memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
if (num != 1)
return NS_ERROR_FAILURE;
float hueRotateValue;
list->GetItem(0, getter_AddRefs(number));
number->GetValue(&hueRotateValue);
c = NS_STATIC_CAST(float, cos(hueRotateValue * M_PI / 180));
s = NS_STATIC_CAST(float, sin(hueRotateValue * M_PI / 180));
memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
colorMatrix[0] = 0.213f + 0.787f * c - 0.213f * s;
colorMatrix[1] = 0.715f - 0.715f * c - 0.715f * s;
colorMatrix[2] = 0.072f - 0.072f * c + 0.928f * s;
colorMatrix[5] = 0.213f - 0.213f * c + 0.143f * s;
colorMatrix[6] = 0.715f + 0.285f * c + 0.140f * s;
colorMatrix[7] = 0.072f - 0.072f * c - 0.283f * s;
colorMatrix[10] = 0.213f - 0.213f * c - 0.787f * s;
colorMatrix[11] = 0.715f - 0.715f * c + 0.715f * s;
colorMatrix[12] = 0.072f + 0.928f * c + 0.072f * s;
break;
case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA:
memcpy(colorMatrix, luminanceToAlphaMatrix, sizeof(colorMatrix));
break;
default:
return NS_ERROR_FAILURE;
}
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
PRUint32 targIndex = y * stride + 4 * x;
float col[4];
for (int i = 0, row = 0; i < 4; i++, row += 5) {
col[i] = sourceData[targIndex + 2] * colorMatrix[row + 0] +
sourceData[targIndex + 1] * colorMatrix[row + 1] +
sourceData[targIndex + 0] * colorMatrix[row + 2] +
sourceData[targIndex + 3] * colorMatrix[row + 3] +
255 * colorMatrix[row + 4];
col[i] = PR_MIN(PR_MAX(0, col[i]), 255);
}
targetData[targIndex + 2] = NS_STATIC_CAST(PRUint8, col[0]);
targetData[targIndex + 1] = NS_STATIC_CAST(PRUint8, col[1]);
targetData[targIndex + 0] = NS_STATIC_CAST(PRUint8, col[2]);
targetData[targIndex + 3] = NS_STATIC_CAST(PRUint8, col[3]);
}
}
return NS_OK;
}
//---------------------Composite------------------------
typedef nsSVGFE nsSVGFECompositeElementBase;
@ -1286,7 +1604,6 @@ nsSVGFECompositeElement::GetNumberInfo()
NS_ARRAY_LENGTH(sNumberInfo));
}
//---------------------Component Transfer------------------------
typedef nsSVGFE nsSVGFEComponentTransferElementBase;

Просмотреть файл

@ -69,6 +69,21 @@ interface nsIDOMSVGFEBlendElement : nsIDOMSVGFilterPrimitiveStandardAttributes
readonly attribute nsIDOMSVGAnimatedEnumeration mode;
};
[scriptable, uuid(0E966878-EBF1-4455-86FD-F4C7B1F24777)]
interface nsIDOMSVGFEColorMatrixElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{
// Color Matrix Types
const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0;
const unsigned short SVG_FECOLORMATRIX_TYPE_MATRIX = 1;
const unsigned short SVG_FECOLORMATRIX_TYPE_SATURATE = 2;
const unsigned short SVG_FECOLORMATRIX_TYPE_HUE_ROTATE = 3;
const unsigned short SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA = 4;
readonly attribute nsIDOMSVGAnimatedString in1;
readonly attribute nsIDOMSVGAnimatedEnumeration type;
readonly attribute nsIDOMSVGAnimatedNumberList values;
};
[scriptable, uuid(4de6b44a-f909-4948-bc43-5ee2ca6de55b)]
interface nsIDOMSVGFEComponentTransferElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{

Просмотреть файл

@ -246,6 +246,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_SVGDescElement_id,
eDOMClassInfo_SVGEllipseElement_id,
eDOMClassInfo_SVGFEBlendElement_id,
eDOMClassInfo_SVGFEColorMatrixElement_id,
eDOMClassInfo_SVGFEComponentTransferElement_id,
eDOMClassInfo_SVGFECompositeElement_id,
eDOMClassInfo_SVGFEFloodElement_id,

Просмотреть файл

@ -904,6 +904,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEBlendElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEColorMatrixElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEComponentTransferElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFECompositeElement, nsElementSH,
@ -2586,6 +2588,13 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEColorMatrixElement, nsIDOMSVGFEColorMatrixElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEColorMatrixElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEComponentTransferElement, nsIDOMSVGFEComponentTransferElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEComponentTransferElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)