Bug 380757 - switch svg filters to thebes. r=jwatt, sr=roc

This commit is contained in:
tor@cs.brown.edu 2007-05-21 14:41:53 -07:00
Родитель 218ecc7055
Коммит 09e9701b1e
3 изменённых файлов: 97 добавлений и 102 удалений

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

@ -59,7 +59,7 @@
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "nsSVGAnimatedInteger.h"
#include "gfxColor.h"
#include "gfxContext.h"
nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] =
{
@ -235,7 +235,7 @@ public:
*/
nsresult AcquireSourceImage(nsIDOMSVGAnimatedString* aIn,
nsSVGFE* aFilter, PRUint8** aSourceData,
cairo_surface_t** aSurface = 0);
gfxImageSurface** aSurface = 0);
/*
* Acquiring a target image will create a new surface to be used as the
* target image.
@ -247,7 +247,7 @@ public:
*/
nsresult AcquireTargetImage(nsIDOMSVGAnimatedString* aResult,
PRUint8** aTargetData,
cairo_surface_t** aSurface = 0);
gfxImageSurface** aSurface = 0);
const nsRect& GetRect() {
return mRect;
}
@ -282,7 +282,7 @@ private:
nsAutoString mInput, mResult;
nsRect mRect;
cairo_surface_t *mTargetImage;
nsRefPtr<gfxImageSurface> mTargetImage;
nsSVGFilterInstance* mInstance;
PRUint8 *mSourceData, *mTargetData;
PRUint32 mWidth, mHeight;
@ -311,24 +311,26 @@ nsSVGFilterResource::~nsSVGFilterResource()
nsresult
nsSVGFilterResource::AcquireSourceImage(nsIDOMSVGAnimatedString* aIn,
nsSVGFE* aFilter, PRUint8** aSourceData,
cairo_surface_t** aSurface)
gfxImageSurface** aSurface)
{
aIn->GetAnimVal(mInput);
nsRect defaultRect;
cairo_surface_t *surface;
mInstance->LookupImage(mInput, &surface, &defaultRect, mColorModel);
nsRefPtr<gfxImageSurface> surface;
mInstance->LookupImage(mInput, getter_AddRefs(surface),
&defaultRect, mColorModel);
if (!surface) {
return NS_ERROR_FAILURE;
}
if (aSurface) {
*aSurface = surface;
*aSurface = nsnull;
surface.swap(*aSurface);
}
mInstance->GetFilterSubregion(aFilter, defaultRect, &mRect);
mSourceData = cairo_image_surface_get_data(surface);
mStride = cairo_image_surface_get_stride(surface);
mSourceData = surface->Data();
mStride = surface->Stride();
*aSourceData = mSourceData;
return NS_OK;
@ -337,7 +339,7 @@ nsSVGFilterResource::AcquireSourceImage(nsIDOMSVGAnimatedString* aIn,
nsresult
nsSVGFilterResource::AcquireTargetImage(nsIDOMSVGAnimatedString* aResult,
PRUint8** aTargetData,
cairo_surface_t** aSurface)
gfxImageSurface** aSurface)
{
aResult->GetAnimVal(mResult);
mTargetImage = mInstance->GetImage();
@ -346,12 +348,14 @@ nsSVGFilterResource::AcquireTargetImage(nsIDOMSVGAnimatedString* aResult,
}
if (aSurface) {
NS_ADDREF(mTargetImage);
*aSurface = mTargetImage;
}
mTargetData = cairo_image_surface_get_data(mTargetImage);
mStride = cairo_image_surface_get_stride(mTargetImage);
mWidth = cairo_image_surface_get_width(mTargetImage);
mHeight = cairo_image_surface_get_height(mTargetImage);
mTargetData = mTargetImage->Data();
mStride = mTargetImage->Stride();
gfxIntSize size = mTargetImage->GetSize();
mWidth = size.width;
mHeight = size.height;
*aTargetData = mTargetData;
return NS_OK;
@ -365,8 +369,6 @@ nsSVGFilterResource::ReleaseTarget()
}
mInstance->DefineImage(mResult, mTargetImage, mRect, mColorModel);
// filter instance now owns the image
cairo_surface_destroy(mTargetImage);
mTargetImage = nsnull;
}
@ -1510,13 +1512,15 @@ nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
cairo_surface_t *sourceSurface, *targetSurface;
nsRefPtr<gfxImageSurface> sourceSurface, targetSurface;
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn2, this, &sourceData, &sourceSurface);
rv = fr.AcquireSourceImage(mIn2, this, &sourceData,
getter_AddRefs(sourceSurface));
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
rv = fr.AcquireTargetImage(mResult, &targetData,
getter_AddRefs(targetSurface));
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 op;
@ -1568,29 +1572,27 @@ nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance)
}
// Cairo supports the operation we are trying to perform
cairo_t *cr = cairo_create(targetSurface);
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(cr);
return NS_ERROR_FAILURE;
}
gfxContext ctx(targetSurface);
cairo_set_source_surface(cr, sourceSurface, 0, 0);
cairo_paint(cr);
ctx.SetSource(sourceSurface);
ctx.Paint();
if (op < SVG_OPERATOR_OVER || op > SVG_OPERATOR_XOR) {
cairo_destroy(cr);
return NS_ERROR_FAILURE;
}
cairo_operator_t opMap[] = { CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT,
CAIRO_OPERATOR_ATOP, CAIRO_OPERATOR_XOR };
cairo_set_operator(cr, opMap[op]);
gfxContext::GraphicsOperator opMap[] = { gfxContext::OPERATOR_DEST,
gfxContext::OPERATOR_OVER,
gfxContext::OPERATOR_IN,
gfxContext::OPERATOR_OUT,
gfxContext::OPERATOR_ATOP,
gfxContext::OPERATOR_XOR };
ctx.SetOperator(opMap[op]);
rv = fr.AcquireSourceImage(mIn1, this, &sourceData, &sourceSurface);
rv = fr.AcquireSourceImage(mIn1, this, &sourceData,
getter_AddRefs(sourceSurface));
NS_ENSURE_SUCCESS(rv, rv);
cairo_set_source_surface(cr, sourceSurface, 0, 0);
cairo_paint(cr);
cairo_destroy(cr);
ctx.SetSource(sourceSurface);
ctx.Paint();
return NS_OK;
}
@ -2266,18 +2268,15 @@ nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
cairo_surface_t *sourceSurface, *targetSurface;
nsRefPtr<gfxImageSurface> sourceSurface, targetSurface;
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
rv = fr.AcquireTargetImage(mResult, &targetData,
getter_AddRefs(targetSurface));
NS_ENSURE_SUCCESS(rv, rv);
cairo_t *cr = cairo_create(targetSurface);
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(cr);
return NS_ERROR_FAILURE;
}
gfxContext ctx(targetSurface);
PRUint32 count = GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
@ -2288,13 +2287,13 @@ nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance)
nsCOMPtr<nsIDOMSVGAnimatedString> str;
node->GetIn1(getter_AddRefs(str));
rv = fr.AcquireSourceImage(str, this, &sourceData, &sourceSurface);
rv = fr.AcquireSourceImage(str, this, &sourceData,
getter_AddRefs(sourceSurface));
NS_ENSURE_SUCCESS(rv, rv);
cairo_set_source_surface(cr, sourceSurface, 0, 0);
cairo_paint(cr);
ctx.SetSource(sourceSurface);
ctx.Paint();
}
cairo_destroy(cr);
return NS_OK;
}
@ -2705,7 +2704,7 @@ nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
cairo_surface_t *targetSurface;
nsRefPtr<gfxImageSurface> targetSurface;
// flood colour is sRGB
nsSVGFilterInstance::ColorModel
colorModel(nsSVGFilterInstance::ColorModel::SRGB,
@ -2714,7 +2713,8 @@ nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance)
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
rv = fr.AcquireTargetImage(mResult, &targetData,
getter_AddRefs(targetSurface));
NS_ENSURE_SUCCESS(rv, rv);
nsRect rect = fr.GetRect();
@ -2725,19 +2725,13 @@ nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance)
nscolor floodColor = style->GetStyleSVGReset()->mFloodColor;
float floodOpacity = style->GetStyleSVGReset()->mFloodOpacity;
cairo_t *cr = cairo_create(targetSurface);
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(cr);
return NS_ERROR_FAILURE;
}
cairo_set_source_rgba(cr,
NS_GET_R(floodColor) / 255.0,
NS_GET_G(floodColor) / 255.0,
NS_GET_B(floodColor) / 255.0,
NS_GET_A(floodColor) / 255.0 * floodOpacity);
cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height);
cairo_fill(cr);
cairo_destroy(cr);
gfxContext ctx(targetSurface);
ctx.SetColor(gfxRGBA(NS_GET_R(floodColor) / 255.0,
NS_GET_G(floodColor) / 255.0,
NS_GET_B(floodColor) / 255.0,
NS_GET_A(floodColor) / 255.0 * floodOpacity));
ctx.Rectangle(gfxRect(rect.x, rect.y, rect.width, rect.height));
ctx.Fill();
return NS_OK;
}

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

@ -218,7 +218,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
// paint the target geometry
nsRefPtr<gfxImageSurface> tmpSurface =
new gfxImageSurface(gfxIntSize(filterResX, filterResY), gfxASurface::ImageFormatARGB32);
new gfxImageSurface(gfxIntSize(filterResX, filterResY),
gfxASurface::ImageFormatARGB32);
if (!tmpSurface || !tmpSurface->Data()) {
FilterFailCleanup(aContext, aTarget);
return NS_OK;
@ -227,7 +228,10 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
gfxContext tmpContext(tmpSurface);
nsSVGRenderState tmpState(&tmpContext);
memset(tmpSurface->Data(), 0, tmpSurface->GetSize().height * tmpSurface->Stride());
tmpContext.SetOperator(gfxContext::OPERATOR_CLEAR);
tmpContext.Paint();
tmpContext.SetOperator(gfxContext::OPERATOR_OVER);
aTarget->PaintSVG(&tmpState, nsnull);
PRUint16 primitiveUnits;
@ -241,19 +245,17 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsSVGFilterInstance::ColorModel::PREMULTIPLIED);
if (requirements & NS_FE_SOURCEALPHA) {
cairo_surface_t *alpha =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
filterResX, filterResY);
nsRefPtr<gfxImageSurface> alpha =
new gfxImageSurface(gfxIntSize(filterResX, filterResY),
gfxASurface::ImageFormatARGB32);
if (!alpha || cairo_surface_status(alpha)) {
if (alpha)
cairo_surface_destroy(alpha);
if (!alpha || !alpha->Data()) {
FilterFailCleanup(aContext, aTarget);
return NS_OK;
}
PRUint8 *data = tmpSurface->Data();
PRUint8 *alphaData = cairo_image_surface_get_data(alpha);
PRUint8 *alphaData = alpha->Data();
PRUint32 stride = tmpSurface->Stride();
for (PRUint32 yy = 0; yy < PRUint32(filterResY); yy++)
@ -262,7 +264,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_G] = 0;
alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_R] = 0;
alphaData[stride*yy + 4*xx + GFX_ARGB32_OFFSET_A] =
data[stride*yy + 4*xx + 3];
data[stride*yy + 4*xx + GFX_ARGB32_OFFSET_A];
}
instance.DefineImage(NS_LITERAL_STRING("SourceAlpha"), alpha,
@ -271,8 +273,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
// this always needs to be defined last because the default image
// for the first filter element is supposed to be SourceGraphic
instance.DefineImage(NS_LITERAL_STRING("SourceGraphic"),
tmpSurface->CairoSurface(),
instance.DefineImage(NS_LITERAL_STRING("SourceGraphic"), tmpSurface,
nsRect(0, 0, filterResX, filterResY), colorModel);
for (PRUint32 k=0; k<count; ++k) {
@ -285,16 +286,13 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
}
}
cairo_surface_t *filterResult = nsnull;
nsRect filterRect;
nsRefPtr<gfxASurface> resultSurface;
nsRefPtr<gfxImageSurface> filterSurface;
instance.LookupImage(NS_LITERAL_STRING(""),
&filterResult, &filterRect, colorModel);
getter_AddRefs(filterSurface), &filterRect, colorModel);
if (filterResult)
resultSurface = gfxASurface::Wrap(filterResult);
if (!resultSurface) {
if (!filterSurface) {
FilterFailCleanup(aContext, aTarget);
return NS_OK;
}
@ -308,7 +306,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
ctm->Multiply(scale, getter_AddRefs(fini));
nsSVGUtils::CompositeSurfaceMatrix(aContext->GetGfxContext(),
resultSurface, fini, 1.0);
filterSurface, fini, 1.0);
aTarget->SetOverrideCTM(nsnull);
aTarget->SetMatrixPropagation(PR_TRUE);
@ -505,23 +503,29 @@ nsSVGFilterInstance::GetFilterSubregion(
#endif
}
cairo_surface_t *
already_AddRefed<gfxImageSurface>
nsSVGFilterInstance::GetImage()
{
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, mFilterResX, mFilterResY);
nsRefPtr<gfxImageSurface> surface =
new gfxImageSurface(gfxIntSize(mFilterResX, mFilterResY),
gfxASurface::ImageFormatARGB32);
if (surface && cairo_surface_status(surface)) {
cairo_surface_destroy(surface);
surface = nsnull;
if (!(surface && surface->Data())) {
return nsnull;
}
return surface;
gfxContext ctx(surface);
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
ctx.Paint();
gfxImageSurface *retval = nsnull;
surface.swap(retval);
return retval;
}
void
nsSVGFilterInstance::LookupImage(const nsAString &aName,
cairo_surface_t **aImage,
gfxImageSurface **aImage,
nsRect *aRegion,
const ColorModel &aRequiredColorModel)
{
@ -534,14 +538,15 @@ nsSVGFilterInstance::LookupImage(const nsAString &aName,
if (entry) {
*aImage = entry->mImage;
NS_ADDREF(*aImage);
*aRegion = entry->mRegion;
if (aRequiredColorModel == entry->mColorModel)
return;
// convert image to desired format
PRUint8 *data = cairo_image_surface_get_data(entry->mImage);
PRInt32 stride = cairo_image_surface_get_stride(entry->mImage);
PRUint8 *data = (*aImage)->Data();
PRInt32 stride = (*aImage)->Stride();
if (entry->mColorModel.mAlphaChannel == ColorModel::PREMULTIPLIED)
nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, entry->mRegion);
@ -566,7 +571,7 @@ nsSVGFilterInstance::LookupImage(const nsAString &aName,
void
nsSVGFilterInstance::DefineImage(const nsAString &aName,
cairo_surface_t *aImage,
gfxImageSurface *aImage,
const nsRect &aRegion,
const ColorModel &aColorModel)
{

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

@ -46,7 +46,7 @@
#include "nsIContent.h"
#include "nsAutoPtr.h"
#include "cairo.h"
#include "gfxImageSurface.h"
class nsSVGLength2;
class nsSVGElement;
@ -75,13 +75,13 @@ public:
nsRect defaultRegion,
nsRect *result);
cairo_surface_t *GetImage();
already_AddRefed<gfxImageSurface> GetImage();
void LookupImage(const nsAString &aName,
cairo_surface_t **aImage,
gfxImageSurface **aImage,
nsRect *aRegion,
const ColorModel &aColorModel);
void DefineImage(const nsAString &aName,
cairo_surface_t *aImage,
gfxImageSurface *aImage,
const nsRect &aRegion,
const ColorModel &aColorModel);
void GetFilterBox(float *x, float *y, float *width, float *height) {
@ -110,17 +110,13 @@ public:
private:
class ImageEntry {
public:
ImageEntry(cairo_surface_t *aImage,
ImageEntry(gfxImageSurface *aImage,
const nsRect &aRegion,
const ColorModel &aColorModel) :
mImage(aImage), mRegion(aRegion), mColorModel(aColorModel) {
cairo_surface_reference(aImage);
}
~ImageEntry() {
cairo_surface_destroy(mImage);
}
cairo_surface_t *mImage;
nsRefPtr<gfxImageSurface> mImage;
nsRect mRegion;
ColorModel mColorModel;
};