diff options
Diffstat (limited to 'WebCore/svg/graphics')
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; |
