Bug 1047477 - "Add support for all blend mode to feBlend". r=longsonr r=bz

This commit is contained in:
Rik Cabanier 2014-09-12 16:32:00 +02:00
parent 0df0355761
commit fb073bbd6b
14 changed files with 276 additions and 130 deletions

View File

@ -1260,6 +1260,8 @@ GK_ATOM(clip_rule, "clip-rule")
GK_ATOM(clipPath, "clipPath")
GK_ATOM(clipPathUnits, "clipPathUnits")
GK_ATOM(cm, "cm")
GK_ATOM(colorBurn, "color-burn")
GK_ATOM(colorDodge, "color-dodge")
GK_ATOM(colorInterpolation, "color-interpolation")
GK_ATOM(colorInterpolationFilters, "color-interpolation-filters")
GK_ATOM(colorProfile, "color-profile")
@ -1288,6 +1290,7 @@ GK_ATOM(elevation, "elevation")
GK_ATOM(erode, "erode")
GK_ATOM(ex, "ex")
GK_ATOM(exact, "exact")
GK_ATOM(exclusion, "exclusion")
GK_ATOM(exponent, "exponent")
GK_ATOM(feBlend, "feBlend")
GK_ATOM(feColorMatrix, "feColorMatrix")
@ -1352,7 +1355,9 @@ GK_ATOM(glyph_orientation_vertical, "glyph-orientation-vertical")
GK_ATOM(grad, "grad")
GK_ATOM(gradientTransform, "gradientTransform")
GK_ATOM(gradientUnits, "gradientUnits")
GK_ATOM(hardLight, "hard-light")
GK_ATOM(hkern, "hkern")
GK_ATOM(hue, "hue")
GK_ATOM(hueRotate, "hueRotate")
GK_ATOM(identity, "identity")
GK_ATOM(image_rendering, "image-rendering")
@ -1376,6 +1381,7 @@ GK_ATOM(linearGradient, "linearGradient")
GK_ATOM(linearRGB, "linearRGB")
GK_ATOM(list_style_type, "list-style-type")
GK_ATOM(luminanceToAlpha, "luminanceToAlpha")
GK_ATOM(luminosity, "luminosity")
GK_ATOM(magnify, "magnify")
GK_ATOM(marker, "marker")
GK_ATOM(marker_end, "marker-end")
@ -1441,6 +1447,7 @@ GK_ATOM(rotate, "rotate")
GK_ATOM(rx, "rx")
GK_ATOM(ry, "ry")
GK_ATOM(saturate, "saturate")
GK_ATOM(saturation, "saturation")
GK_ATOM(set, "set")
GK_ATOM(seed, "seed")
GK_ATOM(shadow, "shadow")
@ -1448,6 +1455,7 @@ GK_ATOM(shape_rendering, "shape-rendering")
GK_ATOM(skewX, "skewX")
GK_ATOM(skewY, "skewY")
GK_ATOM(slope, "slope")
GK_ATOM(softLight, "soft-light")
GK_ATOM(spacing, "spacing")
GK_ATOM(spacingAndGlyphs, "spacingAndGlyphs")
GK_ATOM(specularConstant, "specularConstant")

View File

@ -26,6 +26,17 @@ nsSVGEnumMapping SVGFEBlendElement::sModeMap[] = {
{&nsGkAtoms::screen, SVG_FEBLEND_MODE_SCREEN},
{&nsGkAtoms::darken, SVG_FEBLEND_MODE_DARKEN},
{&nsGkAtoms::lighten, SVG_FEBLEND_MODE_LIGHTEN},
{&nsGkAtoms::overlay, SVG_FEBLEND_MODE_OVERLAY},
{&nsGkAtoms::colorDodge, SVG_FEBLEND_MODE_COLOR_DODGE},
{&nsGkAtoms::colorBurn, SVG_FEBLEND_MODE_COLOR_BURN},
{&nsGkAtoms::hardLight, SVG_FEBLEND_MODE_HARD_LIGHT},
{&nsGkAtoms::softLight, SVG_FEBLEND_MODE_SOFT_LIGHT},
{&nsGkAtoms::difference, SVG_FEBLEND_MODE_DIFFERENCE},
{&nsGkAtoms::exclusion, SVG_FEBLEND_MODE_EXCLUSION},
{&nsGkAtoms::hue, SVG_FEBLEND_MODE_HUE},
{&nsGkAtoms::saturation, SVG_FEBLEND_MODE_SATURATION},
{&nsGkAtoms::color, SVG_FEBLEND_MODE_COLOR},
{&nsGkAtoms::luminosity, SVG_FEBLEND_MODE_LUMINOSITY},
{nullptr, 0}
};

View File

@ -19,7 +19,17 @@ interface SVGFEBlendElement : SVGElement {
const unsigned short SVG_FEBLEND_MODE_SCREEN = 3;
const unsigned short SVG_FEBLEND_MODE_DARKEN = 4;
const unsigned short SVG_FEBLEND_MODE_LIGHTEN = 5;
const unsigned short SVG_FEBLEND_MODE_OVERLAY = 6;
const unsigned short SVG_FEBLEND_MODE_COLOR_DODGE = 7;
const unsigned short SVG_FEBLEND_MODE_COLOR_BURN = 8;
const unsigned short SVG_FEBLEND_MODE_HARD_LIGHT = 9;
const unsigned short SVG_FEBLEND_MODE_SOFT_LIGHT = 10;
const unsigned short SVG_FEBLEND_MODE_DIFFERENCE = 11;
const unsigned short SVG_FEBLEND_MODE_EXCLUSION = 12;
const unsigned short SVG_FEBLEND_MODE_HUE = 13;
const unsigned short SVG_FEBLEND_MODE_SATURATION = 14;
const unsigned short SVG_FEBLEND_MODE_COLOR = 15;
const unsigned short SVG_FEBLEND_MODE_LUMINOSITY = 16;
readonly attribute SVGAnimatedString in1;
readonly attribute SVGAnimatedString in2;
readonly attribute SVGAnimatedEnumeration mode;

View File

@ -57,6 +57,29 @@ D2D1_BLEND_MODE D2DBlendMode(uint32_t aMode)
return D2D1_BLEND_MODE_MULTIPLY;
case BLEND_MODE_SCREEN:
return D2D1_BLEND_MODE_SCREEN;
case BLEND_MODE_OVERLAY:
return D2D1_BLEND_MODE_OVERLAY;
case BLEND_MODE_COLOR_DODGE:
return D2D1_BLEND_MODE_COLOR_DODGE;
case BLEND_MODE_COLOR_BURN:
return D2D1_BLEND_MODE_COLOR_BURN;
case BLEND_MODE_HARD_LIGHT:
return D2D1_BLEND_MODE_HARD_LIGHT;
case BLEND_MODE_SOFT_LIGHT:
return D2D1_BLEND_MODE_SOFT_LIGHT;
case BLEND_MODE_DIFFERENCE:
return D2D1_BLEND_MODE_DIFFERENCE;
case BLEND_MODE_EXCLUSION:
return D2D1_BLEND_MODE_EXCLUSION;
case BLEND_MODE_HUE:
return D2D1_BLEND_MODE_HUE;
case BLEND_MODE_SATURATION:
return D2D1_BLEND_MODE_SATURATION;
case BLEND_MODE_COLOR:
return D2D1_BLEND_MODE_COLOR;
case BLEND_MODE_LUMINOSITY:
return D2D1_BLEND_MODE_LUMINOSITY;
default:
MOZ_CRASH("Unknown enum value!");
}

View File

@ -994,6 +994,46 @@ FilterNodeBlendSoftware::SetAttribute(uint32_t aIndex, uint32_t aBlendMode)
Invalidate();
}
static CompositionOp ToBlendOp(BlendMode aOp)
{
switch (aOp) {
case BLEND_MODE_MULTIPLY:
return CompositionOp::OP_MULTIPLY;
case BLEND_MODE_SCREEN:
return CompositionOp::OP_SCREEN;
case BLEND_MODE_OVERLAY:
return CompositionOp::OP_OVERLAY;
case BLEND_MODE_DARKEN:
return CompositionOp::OP_DARKEN;
case BLEND_MODE_LIGHTEN:
return CompositionOp::OP_LIGHTEN;
case BLEND_MODE_COLOR_DODGE:
return CompositionOp::OP_COLOR_DODGE;
case BLEND_MODE_COLOR_BURN:
return CompositionOp::OP_COLOR_BURN;
case BLEND_MODE_HARD_LIGHT:
return CompositionOp::OP_HARD_LIGHT;
case BLEND_MODE_SOFT_LIGHT:
return CompositionOp::OP_SOFT_LIGHT;
case BLEND_MODE_DIFFERENCE:
return CompositionOp::OP_DIFFERENCE;
case BLEND_MODE_EXCLUSION:
return CompositionOp::OP_EXCLUSION;
case BLEND_MODE_HUE:
return CompositionOp::OP_HUE;
case BLEND_MODE_SATURATION:
return CompositionOp::OP_SATURATION;
case BLEND_MODE_COLOR:
return CompositionOp::OP_COLOR;
case BLEND_MODE_LUMINOSITY:
return CompositionOp::OP_LUMINOSITY;
default:
return CompositionOp::OP_OVER;
}
return CompositionOp::OP_OVER;
}
TemporaryRef<DataSourceSurface>
FilterNodeBlendSoftware::Render(const IntRect& aRect)
{
@ -1010,14 +1050,38 @@ FilterNodeBlendSoftware::Render(const IntRect& aRect)
return nullptr;
}
// Second case: both are non-transparent.
if (input1 && input2) {
// Apply normal filtering.
return FilterProcessing::ApplyBlending(input1, input2, mBlendMode);
// Second case: one of them is transparent. Return the non-transparent one.
if (!input1 || !input2) {
return input1 ? input1.forget() : input2.forget();
}
// Third case: one of them is transparent. Return the non-transparent one.
return input1 ? input1.forget() : input2.forget();
// Third case: both are non-transparent.
// Apply normal filtering.
RefPtr<DataSourceSurface> target = FilterProcessing::ApplyBlending(input1, input2, mBlendMode);
if (target != nullptr) {
return target.forget();
}
IntSize size = input1->GetSize();
target =
Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
if (MOZ2D_WARN_IF(!target)) {
return nullptr;
}
CopyRect(input1, target, IntRect(IntPoint(), size), IntPoint());
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
target->GetData(),
target->GetSize(),
target->Stride(),
target->GetFormat());
Rect r(0, 0, size.width, size.height);
dt->DrawSurface(input2, r, r, DrawSurfaceOptions(), DrawOptions(1.0f, ToBlendOp(mBlendMode)));
dt->Flush();
return target.forget();
}
void

View File

@ -53,7 +53,7 @@ FilterProcessing::ApplyBlending(DataSourceSurface* aInput1, DataSourceSurface* a
return ApplyBlending_SSE2(aInput1, aInput2, aBlendMode);
#endif
}
return ApplyBlending_Scalar(aInput1, aInput2, aBlendMode);
return nullptr;
}
void

View File

@ -67,7 +67,6 @@ public:
protected:
static void ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride);
static TemporaryRef<DataSourceSurface> ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface);
static TemporaryRef<DataSourceSurface> ApplyBlending_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, BlendMode aBlendMode);
static void ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
uint8_t* aDestData, int32_t aDestStride,
const IntRect& aDestRect, int32_t aRadius,

View File

@ -29,84 +29,6 @@ FilterProcessing::ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface)
return ConvertToB8G8R8A8_SIMD<simd::Scalaru8x16_t>(aSurface);
}
template<BlendMode aBlendMode>
static TemporaryRef<DataSourceSurface>
ApplyBlending_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2)
{
IntSize size = aInput1->GetSize();
RefPtr<DataSourceSurface> target =
Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
if (MOZ2D_WARN_IF(!target)) {
return nullptr;
}
uint8_t* source1Data = aInput1->GetData();
uint8_t* source2Data = aInput2->GetData();
uint8_t* targetData = target->GetData();
uint32_t targetStride = target->Stride();
uint32_t source1Stride = aInput1->Stride();
uint32_t source2Stride = aInput2->Stride();
for (int32_t y = 0; y < size.height; y++) {
for (int32_t x = 0; x < size.width; x++) {
uint32_t targetIndex = y * targetStride + 4 * x;
uint32_t source1Index = y * source1Stride + 4 * x;
uint32_t source2Index = y * source2Stride + 4 * x;
uint32_t qa = source1Data[source1Index + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
uint32_t qb = source2Data[source2Index + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
for (int32_t i = std::min(B8G8R8A8_COMPONENT_BYTEOFFSET_B, B8G8R8A8_COMPONENT_BYTEOFFSET_R);
i <= std::max(B8G8R8A8_COMPONENT_BYTEOFFSET_B, B8G8R8A8_COMPONENT_BYTEOFFSET_R); i++) {
uint32_t ca = source1Data[source1Index + i];
uint32_t cb = source2Data[source2Index + i];
uint32_t val;
switch (aBlendMode) {
case BLEND_MODE_MULTIPLY:
val = ((255 - qa) * cb + (255 - qb + cb) * ca);
break;
case BLEND_MODE_SCREEN:
val = 255 * (cb + ca) - ca * cb;
break;
case BLEND_MODE_DARKEN:
val = umin((255 - qa) * cb + 255 * ca,
(255 - qb) * ca + 255 * cb);
break;
case BLEND_MODE_LIGHTEN:
val = umax((255 - qa) * cb + 255 * ca,
(255 - qb) * ca + 255 * cb);
break;
default:
MOZ_CRASH();
}
val = umin(FilterProcessing::FastDivideBy255<unsigned>(val), 255U);
targetData[targetIndex + i] = static_cast<uint8_t>(val);
}
uint32_t alpha = 255 * 255 - (255 - qa) * (255 - qb);
targetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] =
FilterProcessing::FastDivideBy255<uint8_t>(alpha);
}
}
return target.forget();
}
TemporaryRef<DataSourceSurface>
FilterProcessing::ApplyBlending_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2,
BlendMode aBlendMode)
{
switch (aBlendMode) {
case BLEND_MODE_MULTIPLY:
return gfx::ApplyBlending_Scalar<BLEND_MODE_MULTIPLY>(aInput1, aInput2);
case BLEND_MODE_SCREEN:
return gfx::ApplyBlending_Scalar<BLEND_MODE_SCREEN>(aInput1, aInput2);
case BLEND_MODE_DARKEN:
return gfx::ApplyBlending_Scalar<BLEND_MODE_DARKEN>(aInput1, aInput2);
case BLEND_MODE_LIGHTEN:
return gfx::ApplyBlending_Scalar<BLEND_MODE_LIGHTEN>(aInput1, aInput2);
default:
return nullptr;
}
}
template<MorphologyOperator Operator>
static void
ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,

View File

@ -45,7 +45,18 @@ enum BlendMode
BLEND_MODE_MULTIPLY = 0,
BLEND_MODE_SCREEN,
BLEND_MODE_DARKEN,
BLEND_MODE_LIGHTEN
BLEND_MODE_LIGHTEN,
BLEND_MODE_OVERLAY,
BLEND_MODE_COLOR_DODGE,
BLEND_MODE_COLOR_BURN,
BLEND_MODE_HARD_LIGHT,
BLEND_MODE_SOFT_LIGHT,
BLEND_MODE_DIFFERENCE,
BLEND_MODE_EXCLUSION,
BLEND_MODE_HUE,
BLEND_MODE_SATURATION,
BLEND_MODE_COLOR,
BLEND_MODE_LUMINOSITY
};
enum BlendFilterInputs

View File

@ -673,13 +673,24 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
filter->SetInput(IN_COMPOSITE_IN_START + 1, aSources[0]);
} else {
filter = aDT->CreateFilter(FilterType::BLEND);
static const uint8_t blendModes[SVG_FEBLEND_MODE_LIGHTEN + 1] = {
static const uint8_t blendModes[SVG_FEBLEND_MODE_LUMINOSITY + 1] = {
0,
0,
BLEND_MODE_MULTIPLY,
BLEND_MODE_SCREEN,
BLEND_MODE_DARKEN,
BLEND_MODE_LIGHTEN
BLEND_MODE_LIGHTEN,
BLEND_MODE_OVERLAY,
BLEND_MODE_COLOR_DODGE,
BLEND_MODE_COLOR_BURN,
BLEND_MODE_HARD_LIGHT,
BLEND_MODE_SOFT_LIGHT,
BLEND_MODE_DIFFERENCE,
BLEND_MODE_EXCLUSION,
BLEND_MODE_HUE,
BLEND_MODE_SATURATION,
BLEND_MODE_COLOR,
BLEND_MODE_LUMINOSITY
};
filter->SetAttribute(ATT_BLEND_BLENDMODE, (uint32_t)blendModes[mode]);
filter->SetInput(IN_BLEND_IN, aSources[0]);

View File

@ -47,6 +47,17 @@ const unsigned short SVG_FEBLEND_MODE_MULTIPLY = 2;
const unsigned short SVG_FEBLEND_MODE_SCREEN = 3;
const unsigned short SVG_FEBLEND_MODE_DARKEN = 4;
const unsigned short SVG_FEBLEND_MODE_LIGHTEN = 5;
const unsigned short SVG_FEBLEND_MODE_OVERLAY = 6;
const unsigned short SVG_FEBLEND_MODE_COLOR_DODGE = 7;
const unsigned short SVG_FEBLEND_MODE_COLOR_BURN = 8;
const unsigned short SVG_FEBLEND_MODE_HARD_LIGHT = 9;
const unsigned short SVG_FEBLEND_MODE_SOFT_LIGHT = 10;
const unsigned short SVG_FEBLEND_MODE_DIFFERENCE = 11;
const unsigned short SVG_FEBLEND_MODE_EXCLUSION = 12;
const unsigned short SVG_FEBLEND_MODE_HUE = 13;
const unsigned short SVG_FEBLEND_MODE_SATURATION = 14;
const unsigned short SVG_FEBLEND_MODE_COLOR = 15;
const unsigned short SVG_FEBLEND_MODE_LUMINOSITY = 16;
// Edge Mode Values
const unsigned short SVG_EDGEMODE_UNKNOWN = 0;

View File

@ -1,9 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="80" height="80" fill="#00ff00"/>
<rect x="110" y="10" width="80" height="80" fill="#000000"/>
<rect x="210" y="10" width="80" height="80" fill="#ffff00"/>
<rect x="310" y="10" width="80" height="80" fill="#000000"/>
<rect x="410" y="10" width="80" height="80" fill="#ffff00"/>
<rect x="0" y="0" width="50" height="50" fill="#ACCC10"/>
<rect x="50" y="0" width="50" height="50" fill="#B4B43F"/>
<rect x="100" y="0" width="50" height="50" fill="#DFDF3F"/>
<rect x="150" y="0" width="50" height="50" fill="#B4B43F"/>
<rect x="200" y="0" width="50" height="50" fill="#DFDF3F"/>
<rect x="250" y="0" width="50" height="50" fill="#DFB43F"/>
<rect x="300" y="0" width="50" height="50" fill="#DFB43F"/>
<rect x="350" y="0" width="50" height="50" fill="#DFB43F"/>
<rect x="0" y="50" width="50" height="50" fill="#E0B440"/>
<rect x="50" y="50" width="50" height="50" fill="#DFB43F"/>
<rect x="100" y="50" width="50" height="50" fill="#DFDF3F"/>
<rect x="150" y="50" width="50" height="50" fill="#DFDF3F"/>
<rect x="200" y="50" width="50" height="50" fill="#B4CC3F"/>
<rect x="250" y="50" width="50" height="50" fill="#DFB43F"/>
<rect x="300" y="50" width="50" height="50" fill="#B4CC3F"/>
<rect x="350" y="50" width="50" height="50" fill="#DFC88D"/>
</svg>

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 1011 B

View File

@ -1,38 +1,104 @@
<svg xmlns="http://www.w3.org/2000/svg">
<filter id="f1" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox"
x="0%" y="0%" width="100%" height="100%">
<feFlood flood-color="#ff0000" result="flood"/>
<feBlend mode="normal" in="SourceGraphic" in2="flood" x="10%" y="10%" width="80%" height="80%"/>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<filter id="f0" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="normal"/>
</filter>
<rect x="0" y="0" width="100" height="100" fill="#00ff00" filter="url(#f1)"/>
<filter id="f2" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox"
x="0%" y="0%" width="100%" height="100%">
<feFlood flood-color="#ff0000" result="flood"/>
<feBlend mode="multiply" in="SourceGraphic" in2="flood" x="10%" y="10%" width="80%" height="80%"/>
<rect x="0" y="0" width="50" height="50" filter="url(#f0)"/>
<filter id="f1" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="multiply"/>
</filter>
<rect x="100" y="0" width="100" height="100" fill="#00ff00" filter="url(#f2)"/>
<filter id="f3" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox"
x="0%" y="0%" width="100%" height="100%">
<feFlood flood-color="#ff0000" result="flood"/>
<feBlend mode="screen" in="SourceGraphic" in2="flood" x="10%" y="10%" width="80%" height="80%"/>
<rect x="50" y="0" width="50" height="50" filter="url(#f1)"/>
<filter id="f2" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="screen"/>
</filter>
<rect x="200" y="0" width="100" height="100" fill="#00ff00" filter="url(#f3)"/>
<filter id="f4" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox"
x="0%" y="0%" width="100%" height="100%">
<feFlood flood-color="#ff0000" result="flood"/>
<feBlend mode="darken" in="SourceGraphic" in2="flood" x="10%" y="10%" width="80%" height="80%"/>
<rect x="100" y="0" width="50" height="50" filter="url(#f2)"/>
<filter id="f3" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="darken"/>
</filter>
<rect x="300" y="0" width="100" height="100" fill="#00ff00" filter="url(#f4)"/>
<filter id="f5" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox"
x="0%" y="0%" width="100%" height="100%">
<feFlood flood-color="#ff0000" result="flood"/>
<feBlend mode="lighten" in="SourceGraphic" in2="flood" x="10%" y="10%" width="80%" height="80%"/>
<rect x="150" y="0" width="50" height="50" filter="url(#f3)"/>
<filter id="f4" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="lighten"/>
</filter>
<rect x="400" y="0" width="100" height="100" fill="#00ff00" filter="url(#f5)"/>
</svg>
<rect x="200" y="0" width="50" height="50" filter="url(#f4)"/>
<filter id="f5" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="overlay"/>
</filter>
<rect x="250" y="0" width="50" height="50" filter="url(#f5)"/>
<filter id="f6" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="color-dodge"/>
</filter>
<rect x="300" y="0" width="50" height="50" filter="url(#f6)"/>
<filter id="f7" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="color-burn"/>
</filter>
<rect x="350" y="0" width="50" height="50" filter="url(#f7)"/>
<filter id="f8" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="hard-light"/>
</filter>
<rect x="0" y="0" width="50" height="50" filter="url(#f8)"/>
<filter id="f9" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="soft-light"/>
</filter>
<rect x="50" y="50" width="50" height="50" filter="url(#f9)"/>
<filter id="f10" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="difference"/>
</filter>
<rect x="100" y="50" width="50" height="50" filter="url(#f10)"/>
<filter id="f11" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="exclusion"/>
</filter>
<rect x="150" y="50" width="50" height="50" filter="url(#f11)"/>
<filter id="f12" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="hue"/>
</filter>
<rect x="200" y="50" width="50" height="50" filter="url(#f12)"/>
<filter id="f13" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="saturation"/>
</filter>
<rect x="250" y="50" width="50" height="50" filter="url(#f13)"/>
<filter id="f14" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="color"/>
</filter>
<rect x="300" y="50" width="50" height="50" filter="url(#f14)"/>
<filter id="f15" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="luminosity"/>
</filter>
<rect x="350" y="50" width="50" height="50" filter="url(#f15)"/>
<filter id="f16" x="0%" y="0%" width="100%" height="100%">
<feFlood result="a" flood-color="rgb(255,0,0)" flood-opacity="0.5"/>
<feFlood result="b" flood-color="rgb(0,255,0)" flood-opacity="0.5"/>
<feBlend in="a" in2="b" mode="undefined"/>
</filter>
<rect x="0" y="50" width="50" height="50" filter="url(#f16)"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -18,7 +18,7 @@ include svg-filter-chains/reftest.list
== dynamic-filter-invalidation-01.svg pass.svg
== dynamic-filter-invalidation-02.svg pass.svg
== feBlend-1.svg feBlend-1-ref.svg
fuzzy(1,40000) == feBlend-1.svg feBlend-1-ref.svg
== feBlend-2.svg feBlend-2-ref.svg
fuzzy-if(d2d,1,6400) == feColorMatrix-1.svg feColorMatrix-1-ref.svg