summaryrefslogtreecommitdiffstats
path: root/WebCore/svg/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/svg/graphics')
-rw-r--r--WebCore/svg/graphics/SVGImage.cpp2
-rw-r--r--WebCore/svg/graphics/SVGImage.h2
-rw-r--r--WebCore/svg/graphics/SVGPaintServerGradient.cpp2
-rw-r--r--WebCore/svg/graphics/SVGPaintServerPattern.cpp2
-rw-r--r--WebCore/svg/graphics/SVGPaintServerSolid.cpp5
-rw-r--r--WebCore/svg/graphics/SVGResource.cpp2
-rw-r--r--WebCore/svg/graphics/SVGResourceFilter.cpp65
-rw-r--r--WebCore/svg/graphics/SVGResourceFilter.h12
-rw-r--r--WebCore/svg/graphics/filters/SVGDistantLightSource.h16
-rw-r--r--WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp6
-rw-r--r--WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h6
-rw-r--r--WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp54
-rw-r--r--WebCore/svg/graphics/filters/SVGFEFlood.cpp2
-rw-r--r--WebCore/svg/graphics/filters/SVGFEMerge.cpp4
-rw-r--r--WebCore/svg/graphics/filters/SVGFEMorphology.cpp78
-rw-r--r--WebCore/svg/graphics/filters/SVGFEOffset.cpp19
-rw-r--r--WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp6
-rw-r--r--WebCore/svg/graphics/filters/SVGFESpecularLighting.h6
-rw-r--r--WebCore/svg/graphics/filters/SVGFETile.cpp15
-rw-r--r--WebCore/svg/graphics/filters/SVGFilter.cpp5
-rw-r--r--WebCore/svg/graphics/filters/SVGFilter.h12
-rw-r--r--WebCore/svg/graphics/filters/SVGLightSource.h1
-rw-r--r--WebCore/svg/graphics/filters/SVGPointLightSource.h14
-rw-r--r--WebCore/svg/graphics/filters/SVGSpotLightSource.h22
24 files changed, 295 insertions, 63 deletions
diff --git a/WebCore/svg/graphics/SVGImage.cpp b/WebCore/svg/graphics/SVGImage.cpp
index 0a506f8..c4be11e 100644
--- a/WebCore/svg/graphics/SVGImage.cpp
+++ b/WebCore/svg/graphics/SVGImage.cpp
@@ -173,7 +173,7 @@ bool SVGImage::hasRelativeHeight() const
return rootElement->height().unitType() == LengthTypePercentage;
}
-void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp)
{
if (!m_page)
return;
diff --git a/WebCore/svg/graphics/SVGImage.h b/WebCore/svg/graphics/SVGImage.h
index 2cea91a..10f39ba 100644
--- a/WebCore/svg/graphics/SVGImage.h
+++ b/WebCore/svg/graphics/SVGImage.h
@@ -64,7 +64,7 @@ namespace WebCore {
virtual NativeImagePtr frameAtIndex(size_t) { return 0; }
SVGImage(ImageObserver*);
- virtual void draw(GraphicsContext*, const FloatRect& fromRect, const FloatRect& toRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& fromRect, const FloatRect& toRect, ColorSpace styleColorSpace, CompositeOperator);
virtual NativeImagePtr nativeImageForCurrentFrame();
diff --git a/WebCore/svg/graphics/SVGPaintServerGradient.cpp b/WebCore/svg/graphics/SVGPaintServerGradient.cpp
index 4a8e9e0..74e3c22 100644
--- a/WebCore/svg/graphics/SVGPaintServerGradient.cpp
+++ b/WebCore/svg/graphics/SVGPaintServerGradient.cpp
@@ -233,7 +233,7 @@ bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject
// lines or rectangles without width or height.
if (bbox.width() == 0 || bbox.height() == 0) {
Color color(0, 0, 0);
- context->setStrokeColor(color);
+ context->setStrokeColor(color, object->style()->colorSpace());
return true;
}
matrix.translate(bbox.x(), bbox.y());
diff --git a/WebCore/svg/graphics/SVGPaintServerPattern.cpp b/WebCore/svg/graphics/SVGPaintServerPattern.cpp
index e825a0b..289c40c 100644
--- a/WebCore/svg/graphics/SVGPaintServerPattern.cpp
+++ b/WebCore/svg/graphics/SVGPaintServerPattern.cpp
@@ -131,7 +131,7 @@ bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject*
tileImageContext->translate(0, patternBoundaries().height());
for (int j = numX; j > 0; j--) {
tileImageContext->translate(patternBoundaries().width(), 0);
- tileImageContext->drawImage(tile()->image(), tileRect, tileRect);
+ tileImageContext->drawImage(tile()->image(), object->style()->colorSpace(), tileRect, tileRect);
}
tileImageContext->translate(-patternBoundaries().width() * numX, 0);
}
diff --git a/WebCore/svg/graphics/SVGPaintServerSolid.cpp b/WebCore/svg/graphics/SVGPaintServerSolid.cpp
index b333042..72baad2 100644
--- a/WebCore/svg/graphics/SVGPaintServerSolid.cpp
+++ b/WebCore/svg/graphics/SVGPaintServerSolid.cpp
@@ -64,10 +64,11 @@ bool SVGPaintServerSolid::setup(GraphicsContext*& context, const RenderObject* o
{
RenderStyle* style = object ? object->style() : 0;
const SVGRenderStyle* svgStyle = style ? style->svgStyle() : 0;
+ ColorSpace colorSpace = style ? style->colorSpace() : DeviceColorSpace;
if ((type & ApplyToFillTargetType) && (!style || svgStyle->hasFill())) {
context->setAlpha(style ? svgStyle->fillOpacity() : 1);
- context->setFillColor(color().rgb());
+ context->setFillColor(color().rgb(), colorSpace);
context->setFillRule(style ? svgStyle->fillRule() : RULE_NONZERO);
if (isPaintingText)
@@ -76,7 +77,7 @@ bool SVGPaintServerSolid::setup(GraphicsContext*& context, const RenderObject* o
if ((type & ApplyToStrokeTargetType) && (!style || svgStyle->hasStroke())) {
context->setAlpha(style ? svgStyle->strokeOpacity() : 1);
- context->setStrokeColor(color().rgb());
+ context->setStrokeColor(color().rgb(), colorSpace);
if (style)
applyStrokeStyleToContext(context, style, object);
diff --git a/WebCore/svg/graphics/SVGResource.cpp b/WebCore/svg/graphics/SVGResource.cpp
index 049edc7..514b70d 100644
--- a/WebCore/svg/graphics/SVGResource.cpp
+++ b/WebCore/svg/graphics/SVGResource.cpp
@@ -39,7 +39,7 @@ SVGResource::SVGResource()
{
}
-struct ResourceSet {
+struct ResourceSet : Noncopyable {
ResourceSet()
{
for (int i = 0; i < _ResourceTypeCount; i++)
diff --git a/WebCore/svg/graphics/SVGResourceFilter.cpp b/WebCore/svg/graphics/SVGResourceFilter.cpp
index 973743c..fcf0e40 100644
--- a/WebCore/svg/graphics/SVGResourceFilter.cpp
+++ b/WebCore/svg/graphics/SVGResourceFilter.cpp
@@ -35,6 +35,10 @@
#include "SVGRenderTreeAsText.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
+static const float kMaxFilterSize = 5000.0f;
+
+using std::min;
+
namespace WebCore {
SVGResourceFilter::SVGResourceFilter(const SVGFilterElement* ownerElement)
@@ -42,6 +46,9 @@ SVGResourceFilter::SVGResourceFilter(const SVGFilterElement* ownerElement)
, m_ownerElement(ownerElement)
, m_filterBBoxMode(false)
, m_effectBBoxMode(false)
+ , m_filterRes(false)
+ , m_scaleX(1.f)
+ , m_scaleY(1.f)
, m_savedContext(0)
, m_sourceGraphicBuffer(0)
{
@@ -52,27 +59,72 @@ SVGResourceFilter::~SVGResourceFilter()
{
}
+static inline bool shouldProcessFilter(SVGResourceFilter* filter)
+{
+ return (!filter->scaleX() || !filter->scaleY() || !filter->filterBoundingBox().width()
+ || !filter->filterBoundingBox().height());
+}
+
void SVGResourceFilter::addFilterEffect(SVGFilterPrimitiveStandardAttributes* effectAttributes, PassRefPtr<FilterEffect> effect)
{
effectAttributes->setStandardAttributes(this, effect.get());
builder()->add(effectAttributes->result(), effect);
}
+bool SVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size)
+{
+ bool matchesFilterSize = true;
+ if (size.width() > kMaxFilterSize) {
+ m_scaleX *= kMaxFilterSize / size.width();
+ matchesFilterSize = false;
+ }
+ if (size.height() > kMaxFilterSize) {
+ m_scaleY *= kMaxFilterSize / size.height();
+ matchesFilterSize = false;
+ }
+
+ return matchesFilterSize;
+}
+
void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object)
{
FloatRect targetRect = object->objectBoundingBox();
m_ownerElement->buildFilter(targetRect);
+ if (shouldProcessFilter(this))
+ return;
+
// clip sourceImage to filterRegion
FloatRect clippedSourceRect = targetRect;
clippedSourceRect.intersect(m_filterBBox);
+ // scale filter size to filterRes
+ FloatRect tempSourceRect = clippedSourceRect;
+ if (m_filterRes) {
+ m_scaleX = m_filterResSize.width() / m_filterBBox.width();
+ m_scaleY = m_filterResSize.height() / m_filterBBox.height();
+ }
+
+ // scale to big sourceImage size to kMaxFilterSize
+ tempSourceRect.scale(m_scaleX, m_scaleY);
+ fitsInMaximumImageSize(tempSourceRect.size());
+
// prepare Filters
m_filter = SVGFilter::create(targetRect, m_filterBBox, m_effectBBoxMode);
+ m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY));
FilterEffect* lastEffect = m_filterBuilder->lastEffect();
- if (lastEffect)
+ if (lastEffect) {
lastEffect->calculateEffectRect(m_filter.get());
+ // at least one FilterEffect has a too big image size,
+ // recalculate the effect sizes with new scale factors
+ if (!fitsInMaximumImageSize(m_filter->maxImageSize())) {
+ m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY));
+ lastEffect->calculateEffectRect(m_filter.get());
+ }
+ }
+
+ clippedSourceRect.scale(m_scaleX, m_scaleY);
// Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic.
// The size of the SourceGraphic is clipped to the size of the filterRegion.
@@ -83,6 +135,7 @@ void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObj
return;
GraphicsContext* sourceGraphicContext = sourceGraphic->context();
+ sourceGraphicContext->scale(FloatSize(m_scaleX, m_scaleY));
sourceGraphicContext->translate(-targetRect.x(), -targetRect.y());
sourceGraphicContext->clearRect(FloatRect(FloatPoint(), targetRect.size()));
m_sourceGraphicBuffer.set(sourceGraphic.release());
@@ -91,8 +144,11 @@ void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObj
context = sourceGraphicContext;
}
-void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObject*)
+void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObject* object)
{
+ if (shouldProcessFilter(this))
+ return;
+
if (!m_savedContext)
return;
@@ -113,7 +169,10 @@ void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObjec
#if !PLATFORM(CG)
resultImage->transformColorSpace(LinearRGB, DeviceRGB);
#endif
- context->drawImage(resultImage->image(), lastEffect->subRegion());
+ ColorSpace colorSpace = DeviceColorSpace;
+ if (object)
+ colorSpace = object->style()->colorSpace();
+ context->drawImage(resultImage->image(), colorSpace, lastEffect->subRegion());
}
}
diff --git a/WebCore/svg/graphics/SVGResourceFilter.h b/WebCore/svg/graphics/SVGResourceFilter.h
index 86b11fe..ffd926d 100644
--- a/WebCore/svg/graphics/SVGResourceFilter.h
+++ b/WebCore/svg/graphics/SVGResourceFilter.h
@@ -53,6 +53,9 @@ public:
virtual SVGResourceType resourceType() const { return FilterResourceType; }
+ void setFilterResolution(const FloatSize& filterResSize) { m_filterResSize = filterResSize; }
+ void setHasFilterResolution(bool filterRes) { m_filterRes = filterRes; }
+
bool filterBoundingBoxMode() const { return m_filterBBoxMode; }
void setFilterBoundingBoxMode(bool bboxMode) { m_filterBBoxMode = bboxMode; }
@@ -62,12 +65,17 @@ public:
FloatRect filterRect() const { return m_filterRect; }
void setFilterRect(const FloatRect& rect) { m_filterRect = rect; }
+ float scaleX() const { return m_scaleX; }
+ float scaleY() const { return m_scaleY; }
+
FloatRect filterBoundingBox() { return m_filterBBox; }
void setFilterBoundingBox(const FloatRect& rect) { m_filterBBox = rect; }
void prepareFilter(GraphicsContext*&, const RenderObject*);
void applyFilter(GraphicsContext*&, const RenderObject*);
+ bool fitsInMaximumImageSize(const FloatSize&);
+
void addFilterEffect(SVGFilterPrimitiveStandardAttributes*, PassRefPtr<FilterEffect>);
SVGFilterBuilder* builder() { return m_filterBuilder.get(); }
@@ -81,9 +89,13 @@ private:
bool m_filterBBoxMode : 1;
bool m_effectBBoxMode : 1;
+ bool m_filterRes : 1;
+ float m_scaleX;
+ float m_scaleY;
FloatRect m_filterRect;
FloatRect m_filterBBox;
+ FloatSize m_filterResSize;
OwnPtr<SVGFilterBuilder> m_filterBuilder;
GraphicsContext* m_savedContext;
diff --git a/WebCore/svg/graphics/filters/SVGDistantLightSource.h b/WebCore/svg/graphics/filters/SVGDistantLightSource.h
index 07ac16c..db9b59d 100644
--- a/WebCore/svg/graphics/filters/SVGDistantLightSource.h
+++ b/WebCore/svg/graphics/filters/SVGDistantLightSource.h
@@ -30,11 +30,10 @@ namespace WebCore {
class DistantLightSource : public LightSource {
public:
- DistantLightSource(float azimuth, float elevation)
- : LightSource(LS_DISTANT)
- , m_azimuth(azimuth)
- , m_elevation(elevation)
- { }
+ static PassRefPtr<DistantLightSource> create(float azimuth, float elevation)
+ {
+ return adoptRef(new DistantLightSource(azimuth, elevation));
+ }
float azimuth() const { return m_azimuth; }
float elevation() const { return m_elevation; }
@@ -42,6 +41,13 @@ namespace WebCore {
virtual TextStream& externalRepresentation(TextStream&) const;
private:
+ DistantLightSource(float azimuth, float elevation)
+ : LightSource(LS_DISTANT)
+ , m_azimuth(azimuth)
+ , m_elevation(elevation)
+ {
+ }
+
float m_azimuth;
float m_elevation;
};
diff --git a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp
index c536478..93921df 100644
--- a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp
@@ -30,7 +30,7 @@
namespace WebCore {
FEDiffuseLighting::FEDiffuseLighting(FilterEffect* in , const Color& lightingColor, const float& surfaceScale,
- const float& diffuseConstant, const float& kernelUnitLengthX, const float& kernelUnitLengthY, LightSource* lightSource)
+ const float& diffuseConstant, const float& kernelUnitLengthX, const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource)
: FilterEffect()
, m_in(in)
, m_lightingColor(lightingColor)
@@ -44,7 +44,7 @@ FEDiffuseLighting::FEDiffuseLighting(FilterEffect* in , const Color& lightingCol
PassRefPtr<FEDiffuseLighting> FEDiffuseLighting::create(FilterEffect* in , const Color& lightingColor,
const float& surfaceScale, const float& diffuseConstant, const float& kernelUnitLengthX,
- const float& kernelUnitLengthY, LightSource* lightSource)
+ const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource)
{
return adoptRef(new FEDiffuseLighting(in, lightingColor, surfaceScale, diffuseConstant, kernelUnitLengthX, kernelUnitLengthY, lightSource));
}
@@ -108,7 +108,7 @@ const LightSource* FEDiffuseLighting::lightSource() const
return m_lightSource.get();
}
-void FEDiffuseLighting::setLightSource(LightSource* lightSource)
+void FEDiffuseLighting::setLightSource(PassRefPtr<LightSource> lightSource)
{
m_lightSource = lightSource;
}
diff --git a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h
index 71f8e22..bf7f28e 100644
--- a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h
+++ b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h
@@ -34,7 +34,7 @@ namespace WebCore {
class FEDiffuseLighting : public FilterEffect {
public:
static PassRefPtr<FEDiffuseLighting> create(FilterEffect*, const Color&, const float&, const float&,
- const float&, const float&, LightSource*);
+ const float&, const float&, PassRefPtr<LightSource>);
virtual ~FEDiffuseLighting();
Color lightingColor() const;
@@ -53,7 +53,7 @@ namespace WebCore {
void setKernelUnitLengthY(float);
const LightSource* lightSource() const;
- void setLightSource(LightSource*);
+ void setLightSource(PassRefPtr<LightSource>);
virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); }
void apply(Filter*);
@@ -62,7 +62,7 @@ namespace WebCore {
private:
FEDiffuseLighting(FilterEffect*, const Color&, const float&, const float&,
- const float&, const float&, LightSource*);
+ const float&, const float&, PassRefPtr<LightSource>);
RefPtr<FilterEffect> m_in;
Color m_lightingColor;
diff --git a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp
index abb57ee..a22bc94 100644
--- a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -23,8 +24,12 @@
#if ENABLE(SVG) && ENABLE(FILTERS)
#include "SVGFEDisplacementMap.h"
-#include "SVGRenderTreeAsText.h"
+
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "SVGRenderTreeAsText.h"
namespace WebCore {
@@ -75,8 +80,53 @@ void FEDisplacementMap::setScale(float scale)
m_scale = scale;
}
-void FEDisplacementMap::apply(Filter*)
+void FEDisplacementMap::apply(Filter* filter)
{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN)
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data());
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+
+ ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
+
+ float scaleX = m_scale / 255.f * filter->filterResolution().width();
+ float scaleY = m_scale / 255.f * filter->filterResolution().height();
+ float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width();
+ float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height();
+ int stride = imageRect.width() * 4;
+ for (int y = 0; y < imageRect.height(); ++y) {
+ int line = y * stride;
+ for (int x = 0; x < imageRect.width(); ++x) {
+ int dstIndex = line + x * 4;
+ int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX);
+ int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY);
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ if (srcX < 0 || srcX >= imageRect.width() || srcY < 0 || srcY >= imageRect.height())
+ imageData->data()->set(dstIndex + channel, static_cast<unsigned char>(0));
+ else {
+ unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel);
+ imageData->data()->set(dstIndex + channel, pixelValue);
+ }
+ }
+
+ }
+ }
+ resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEDisplacementMap::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFEFlood.cpp b/WebCore/svg/graphics/filters/SVGFEFlood.cpp
index 668209f..648bf54 100644
--- a/WebCore/svg/graphics/filters/SVGFEFlood.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEFlood.cpp
@@ -70,7 +70,7 @@ void FEFlood::apply(Filter*)
return;
Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
- filterContext->fillRect(FloatRect(FloatPoint(), subRegion().size()), color);
+ filterContext->fillRect(FloatRect(FloatPoint(), scaledSubRegion().size()), color, DeviceColorSpace);
}
void FEFlood::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFEMerge.cpp b/WebCore/svg/graphics/filters/SVGFEMerge.cpp
index acf3c45..3f9ad38 100644
--- a/WebCore/svg/graphics/filters/SVGFEMerge.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEMerge.cpp
@@ -78,8 +78,8 @@ void FEMerge::apply(Filter* filter)
return;
for (unsigned i = 0; i < m_mergeInputs.size(); i++) {
- FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->subRegion());
- filterContext->drawImage(m_mergeInputs[i]->resultImage()->image(), destRect);
+ FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->scaledSubRegion());
+ filterContext->drawImage(m_mergeInputs[i]->resultImage()->image(), DeviceColorSpace, destRect);
}
}
diff --git a/WebCore/svg/graphics/filters/SVGFEMorphology.cpp b/WebCore/svg/graphics/filters/SVGFEMorphology.cpp
index f7fc5d8..20d109a 100644
--- a/WebCore/svg/graphics/filters/SVGFEMorphology.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEMorphology.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -23,8 +24,16 @@
#if ENABLE(SVG) && ENABLE(FILTERS)
#include "SVGFEMorphology.h"
-#include "SVGRenderTreeAsText.h"
+
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "ImageData.h"
+#include "SVGRenderTreeAsText.h"
+
+#include <wtf/Vector.h>
+
+using std::min;
+using std::max;
namespace WebCore {
@@ -72,8 +81,73 @@ void FEMorphology::setRadiusY(float radiusY)
m_radiusY = radiusY;
}
-void FEMorphology::apply(Filter*)
+void FEMorphology::apply(Filter* filter)
{
+ m_in->apply(filter);
+ if (!m_in->resultImage())
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ if (!m_radiusX || !m_radiusY)
+ return;
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
+ RefPtr<CanvasPixelArray> srcPixelArray(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data());
+ RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+
+ int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width());
+ int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height());
+ int effectWidth = effectDrawingRect.width() * 4;
+
+ // Limit the radius size to effect width
+ radiusX = min(effectDrawingRect.width() - 1, radiusX);
+
+ Vector<unsigned char> extrema;
+ for (int y = 0; y < effectDrawingRect.height(); ++y) {
+ int startY = max(0, y - radiusY);
+ int endY = min(effectDrawingRect.height() - 1, y + radiusY);
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ // Fill the kernel
+ extrema.clear();
+ for (int j = 0; j <= radiusX; ++j) {
+ unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + 4 * j + channel);
+ for (int i = startY; i <= endY; ++i) {
+ unsigned char pixel = srcPixelArray->get(i * effectWidth + 4 * j + channel);
+ if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) ||
+ (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
+ columnExtrema = pixel;
+ }
+ extrema.append(columnExtrema);
+ }
+
+ // Kernel is filled, get extrema of next column
+ for (int x = 0; x < effectDrawingRect.width(); ++x) {
+ unsigned endX = min(x + radiusX, effectDrawingRect.width() - 1);
+ unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + endX * 4 + channel);
+ for (int i = startY; i <= endY; ++i) {
+ unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + channel);
+ if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) ||
+ (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
+ columnExtrema = pixel;
+ }
+ if (x - radiusX >= 0)
+ extrema.remove(0);
+ if (x + radiusX <= effectDrawingRect.width())
+ extrema.append(columnExtrema);
+ unsigned char entireExtrema = extrema[0];
+ for (unsigned kernelIndex = 0; kernelIndex < extrema.size(); ++kernelIndex) {
+ if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema) ||
+ (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema))
+ entireExtrema = extrema[kernelIndex];
+ }
+ imageData->data()->set(y * effectWidth + 4 * x + channel, entireExtrema);
+ }
+ }
+ }
+ resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEMorphology::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFEOffset.cpp b/WebCore/svg/graphics/filters/SVGFEOffset.cpp
index ce9ee3d..9fd50ed 100644
--- a/WebCore/svg/graphics/filters/SVGFEOffset.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEOffset.cpp
@@ -74,17 +74,22 @@ void FEOffset::apply(Filter* filter)
if (!filterContext)
return;
+ FloatRect sourceImageRect = filter->sourceImageRect();
+ sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+
if (filter->effectBoundingBoxMode()) {
- setDx(dx() * filter->sourceImageRect().width());
- setDy(dy() * filter->sourceImageRect().height());
+ m_dx *= sourceImageRect.width();
+ m_dy *= sourceImageRect.height();
}
+ m_dx *= filter->filterResolution().width();
+ m_dy *= filter->filterResolution().height();
- FloatRect dstRect = FloatRect(dx() + m_in->subRegion().x() - subRegion().x(),
- dy() + m_in->subRegion().y() - subRegion().y(),
- m_in->subRegion().width(),
- m_in->subRegion().height());
+ FloatRect dstRect = FloatRect(m_dx + m_in->scaledSubRegion().x() - scaledSubRegion().x(),
+ m_dy + m_in->scaledSubRegion().y() - scaledSubRegion().y(),
+ m_in->scaledSubRegion().width(),
+ m_in->scaledSubRegion().height());
- filterContext->drawImage(m_in->resultImage()->image(), dstRect);
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, dstRect);
}
void FEOffset::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp b/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp
index eb0c280..0b43aba 100644
--- a/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp
+++ b/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp
@@ -30,7 +30,7 @@ namespace WebCore {
FESpecularLighting::FESpecularLighting(FilterEffect* in, const Color& lightingColor, const float& surfaceScale,
const float& specularConstant, const float& specularExponent, const float& kernelUnitLengthX,
- const float& kernelUnitLengthY, LightSource* lightSource)
+ const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource)
: FilterEffect()
, m_in(in)
, m_lightingColor(lightingColor)
@@ -45,7 +45,7 @@ FESpecularLighting::FESpecularLighting(FilterEffect* in, const Color& lightingCo
PassRefPtr<FESpecularLighting> FESpecularLighting::create(FilterEffect* in, const Color& lightingColor,
const float& surfaceScale, const float& specularConstant, const float& specularExponent,
- const float& kernelUnitLengthX, const float& kernelUnitLengthY, LightSource* lightSource)
+ const float& kernelUnitLengthX, const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource)
{
return adoptRef(new FESpecularLighting(in, lightingColor, surfaceScale, specularConstant, specularExponent,
kernelUnitLengthX, kernelUnitLengthY, lightSource));
@@ -120,7 +120,7 @@ const LightSource* FESpecularLighting::lightSource() const
return m_lightSource.get();
}
-void FESpecularLighting::setLightSource(LightSource* lightSource)
+void FESpecularLighting::setLightSource(PassRefPtr<LightSource> lightSource)
{
m_lightSource = lightSource;
}
diff --git a/WebCore/svg/graphics/filters/SVGFESpecularLighting.h b/WebCore/svg/graphics/filters/SVGFESpecularLighting.h
index dec5163..f4947fd 100644
--- a/WebCore/svg/graphics/filters/SVGFESpecularLighting.h
+++ b/WebCore/svg/graphics/filters/SVGFESpecularLighting.h
@@ -33,7 +33,7 @@ namespace WebCore {
class FESpecularLighting : public FilterEffect {
public:
static PassRefPtr<FESpecularLighting> create(FilterEffect*, const Color&, const float&, const float&,
- const float&, const float&, const float&, LightSource*);
+ const float&, const float&, const float&, PassRefPtr<LightSource>);
virtual ~FESpecularLighting();
Color lightingColor() const;
@@ -55,7 +55,7 @@ namespace WebCore {
void setKernelUnitLengthY(float);
const LightSource* lightSource() const;
- void setLightSource(LightSource*);
+ void setLightSource(PassRefPtr<LightSource>);
virtual FloatRect uniteEffectRect(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); }
void apply(Filter*);
@@ -64,7 +64,7 @@ namespace WebCore {
private:
FESpecularLighting(FilterEffect*, const Color&, const float&, const float&, const float&,
- const float&, const float&, LightSource*);
+ const float&, const float&, PassRefPtr<LightSource>);
RefPtr<FilterEffect> m_in;
Color m_lightingColor;
diff --git a/WebCore/svg/graphics/filters/SVGFETile.cpp b/WebCore/svg/graphics/filters/SVGFETile.cpp
index 3071501..e97f68f 100644
--- a/WebCore/svg/graphics/filters/SVGFETile.cpp
+++ b/WebCore/svg/graphics/filters/SVGFETile.cpp
@@ -58,24 +58,27 @@ void FETile::apply(Filter* filter)
if (!filterContext)
return;
- IntRect tileRect = enclosingIntRect(m_in->subRegion());
+ IntRect tileRect = enclosingIntRect(m_in->scaledSubRegion());
// Source input needs more attention. It has the size of the filterRegion but gives the
// size of the cutted sourceImage back. This is part of the specification and optimization.
- if (m_in->isSourceInput())
- tileRect = enclosingIntRect(filter->filterRegion());
+ if (m_in->isSourceInput()) {
+ FloatRect filterRegion = filter->filterRegion();
+ filterRegion.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ tileRect = enclosingIntRect(filterRegion);
+ }
OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
GraphicsContext* tileImageContext = tileImage->context();
- tileImageContext->drawImage(m_in->resultImage()->image(), IntPoint());
+ tileImageContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, IntPoint());
RefPtr<Pattern> pattern = Pattern::create(tileImage->image(), true, true);
TransformationMatrix matrix;
- matrix.translate(m_in->subRegion().x() - subRegion().x(), m_in->subRegion().y() - subRegion().y());
+ matrix.translate(m_in->scaledSubRegion().x() - scaledSubRegion().x(), m_in->scaledSubRegion().y() - scaledSubRegion().y());
pattern.get()->setPatternSpaceTransform(matrix);
filterContext->setFillPattern(pattern);
- filterContext->fillRect(FloatRect(FloatPoint(), subRegion().size()));
+ filterContext->fillRect(FloatRect(FloatPoint(), scaledSubRegion().size()));
}
void FETile::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFilter.cpp b/WebCore/svg/graphics/filters/SVGFilter.cpp
index 6bfcf39..4ec4e6e 100644
--- a/WebCore/svg/graphics/filters/SVGFilter.cpp
+++ b/WebCore/svg/graphics/filters/SVGFilter.cpp
@@ -34,7 +34,7 @@ SVGFilter::SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool
void SVGFilter::calculateEffectSubRegion(FilterEffect* effect)
{
- FloatRect subRegionBBox = effect->subRegion();
+ FloatRect subRegionBBox = effect->effectBoundaries();
FloatRect useBBox = effect->unionOfChildEffectSubregions();
FloatRect newSubRegion = subRegionBBox;
@@ -70,6 +70,9 @@ void SVGFilter::calculateEffectSubRegion(FilterEffect* effect)
newSubRegion.intersect(m_filterRect);
effect->setSubRegion(newSubRegion);
+ newSubRegion.scale(filterResolution().width(), filterResolution().height());
+ effect->setScaledSubRegion(newSubRegion);
+ m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size());
}
PassRefPtr<SVGFilter> SVGFilter::create(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode)
diff --git a/WebCore/svg/graphics/filters/SVGFilter.h b/WebCore/svg/graphics/filters/SVGFilter.h
index f23d1ea..c4714c6 100644
--- a/WebCore/svg/graphics/filters/SVGFilter.h
+++ b/WebCore/svg/graphics/filters/SVGFilter.h
@@ -24,6 +24,7 @@
#include "Filter.h"
#include "FilterEffect.h"
#include "FloatRect.h"
+#include "FloatSize.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -35,15 +36,18 @@ namespace WebCore {
public:
static PassRefPtr<SVGFilter> create(const FloatRect&, const FloatRect&, bool);
- bool effectBoundingBoxMode() { return m_effectBBoxMode; }
+ virtual bool effectBoundingBoxMode() const { return m_effectBBoxMode; }
- FloatRect filterRegion() { return m_filterRect; }
- FloatRect sourceImageRect() { return m_itemBox; }
- void calculateEffectSubRegion(FilterEffect*);
+ virtual FloatRect filterRegion() const { return m_filterRect; }
+ virtual FloatRect sourceImageRect() const { return m_itemBox; }
+
+ virtual FloatSize maxImageSize() const { return m_maxImageSize; }
+ virtual void calculateEffectSubRegion(FilterEffect*);
private:
SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode);
+ FloatSize m_maxImageSize;
FloatRect m_itemBox;
FloatRect m_filterRect;
bool m_effectBBoxMode;
diff --git a/WebCore/svg/graphics/filters/SVGLightSource.h b/WebCore/svg/graphics/filters/SVGLightSource.h
index 22b43c8..6f0075c 100644
--- a/WebCore/svg/graphics/filters/SVGLightSource.h
+++ b/WebCore/svg/graphics/filters/SVGLightSource.h
@@ -24,6 +24,7 @@
#define SVGLightSource_h
#if ENABLE(SVG) && ENABLE(FILTERS)
+#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
namespace WebCore {
diff --git a/WebCore/svg/graphics/filters/SVGPointLightSource.h b/WebCore/svg/graphics/filters/SVGPointLightSource.h
index 772e278..1e966cc 100644
--- a/WebCore/svg/graphics/filters/SVGPointLightSource.h
+++ b/WebCore/svg/graphics/filters/SVGPointLightSource.h
@@ -31,16 +31,22 @@ namespace WebCore {
class PointLightSource : public LightSource {
public:
- PointLightSource(const FloatPoint3D& position)
- : LightSource(LS_POINT)
- , m_position(position)
- { }
+ static PassRefPtr<PointLightSource> create(const FloatPoint3D& position)
+ {
+ return adoptRef(new PointLightSource(position));
+ }
const FloatPoint3D& position() const { return m_position; }
virtual TextStream& externalRepresentation(TextStream&) const;
private:
+ PointLightSource(const FloatPoint3D& position)
+ : LightSource(LS_POINT)
+ , m_position(position)
+ {
+ }
+
FloatPoint3D m_position;
};
diff --git a/WebCore/svg/graphics/filters/SVGSpotLightSource.h b/WebCore/svg/graphics/filters/SVGSpotLightSource.h
index 9a787fb..05280d2 100644
--- a/WebCore/svg/graphics/filters/SVGSpotLightSource.h
+++ b/WebCore/svg/graphics/filters/SVGSpotLightSource.h
@@ -31,13 +31,11 @@ namespace WebCore {
class SpotLightSource : public LightSource {
public:
- SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, float specularExponent, float limitingConeAngle)
- : LightSource(LS_SPOT)
- , m_position(position)
- , m_direction(direction)
- , m_specularExponent(specularExponent)
- , m_limitingConeAngle(limitingConeAngle)
- { }
+ static PassRefPtr<SpotLightSource> create(const FloatPoint3D& position, const FloatPoint3D& direction,
+ float specularExponent, float limitingConeAngle)
+ {
+ return adoptRef(new SpotLightSource(position, direction, specularExponent, limitingConeAngle));
+ }
const FloatPoint3D& position() const { return m_position; }
const FloatPoint3D& direction() const { return m_direction; }
@@ -48,6 +46,16 @@ namespace WebCore {
virtual TextStream& externalRepresentation(TextStream&) const;
private:
+ SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction,
+ float specularExponent, float limitingConeAngle)
+ : LightSource(LS_SPOT)
+ , m_position(position)
+ , m_direction(direction)
+ , m_specularExponent(specularExponent)
+ , m_limitingConeAngle(limitingConeAngle)
+ {
+ }
+
FloatPoint3D m_position;
FloatPoint3D m_direction;