#include "platform/graphics/filters/SourceGraphic.h"
#include "public/platform/WebPoint.h"
-namespace {
-
-PassRefPtr<SkImageFilter> createMatrixImageFilter(SkScalar matrix[20], SkImageFilter* input)
-{
- RefPtr<SkColorFilter> colorFilter(adoptRef(new SkColorMatrixFilter(matrix)));
- return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input));
-}
-
-};
-
namespace WebCore {
SkiaImageFilterBuilder::SkiaImageFilterBuilder()
{
}
-PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace)
+PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace, bool destinationRequiresValidPreMultipliedPixels)
{
if (!effect)
return nullptr;
- FilterColorSpacePair key(effect, colorSpace);
- FilterBuilderHashMap::iterator it = m_map.find(key);
- if (it != m_map.end()) {
- return it->value;
- } else {
- // Note that we may still need the color transform even if the filter is null
- RefPtr<SkImageFilter> origFilter = effect->createImageFilter(this);
- RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
- m_map.set(key, filter);
- return filter.release();
- }
+ bool requiresPMColorValidation = effect->mayProduceInvalidPreMultipliedPixels() && destinationRequiresValidPreMultipliedPixels;
+
+ if (SkImageFilter* filter = effect->getImageFilter(colorSpace, requiresPMColorValidation))
+ return filter;
+
+ // Note that we may still need the color transform even if the filter is null
+ RefPtr<SkImageFilter> origFilter = requiresPMColorValidation ? effect->createImageFilter(this) : effect->createImageFilterWithoutValidation(this);
+ RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
+ effect->setImageFilter(colorSpace, requiresPMColorValidation, filter.get());
+ if (filter.get() != origFilter.get())
+ effect->setImageFilter(effect->operatingColorSpace(), requiresPMColorValidation, origFilter.get());
+ return filter.release();
}
PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::transformColorSpace(
return false;
ColorSpace currentColorSpace = ColorSpaceDeviceRGB;
-
- RefPtr<SkImageFilter> noopFilter;
- SkScalar matrix[20];
- memset(matrix, 0, 20 * sizeof(SkScalar));
- matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
- noopFilter = createMatrixImageFilter(matrix, 0);
+ SkImageFilter* const nullFilter = 0;
for (size_t i = 0; i < operations.size(); ++i) {
const FilterOperation& op = *operations.at(i);
ReferenceFilter* referenceFilter = toReferenceFilterOperation(op).filter();
if (referenceFilter && referenceFilter->lastEffect()) {
FilterEffect* filterEffect = referenceFilter->lastEffect();
- // Link SourceGraphic to a noop filter that serves as a placholder for
- // the previous filter in the chain. We don't know what color space the
- // interior nodes will request, so we have to populate the map with both
- // options. (Only one of these will actually have a color transform on it.)
- FilterColorSpacePair deviceKey(referenceFilter->sourceGraphic(), ColorSpaceDeviceRGB);
- FilterColorSpacePair linearKey(referenceFilter->sourceGraphic(), ColorSpaceLinearRGB);
- m_map.set(deviceKey, transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceDeviceRGB));
- m_map.set(linearKey, transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceLinearRGB));
+ // Prepopulate SourceGraphic with two image filters: one with a null image
+ // filter, and the other with a colorspace conversion filter.
+ // We don't know what color space the interior nodes will request, so we have to
+ // initialize SourceGraphic with both options.
+ // Since we know SourceGraphic is always PM-valid, we also use
+ // these for the PM-validated options.
+ RefPtr<SkImageFilter> deviceFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
+ RefPtr<SkImageFilter> linearFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceLinearRGB);
+ FilterEffect* sourceGraphic = referenceFilter->sourceGraphic();
+ sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, false, deviceFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceLinearRGB, false, linearFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, true, deviceFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceLinearRGB, true, linearFilter.get());
currentColorSpace = filterEffect->operatingColorSpace();
filter = SkiaImageFilterBuilder::build(filterEffect, currentColorSpace);
- // We might have no reference to the SourceGraphic's Skia filter now, so make
- // sure we don't keep it in the map anymore.
- m_map.remove(deviceKey);
- m_map.remove(linearKey);
filters->appendReferenceFilter(filter.get());
}
break;
filters->appendDropShadowFilter(blink::WebPoint(drop.x(), drop.y()), drop.stdDeviation(), drop.color().rgb());
break;
}
- case FilterOperation::VALIDATED_CUSTOM:
- case FilterOperation::CUSTOM:
- return false; // Not supported.
case FilterOperation::NONE:
break;
}
}
if (currentColorSpace != ColorSpaceDeviceRGB) {
// Transform to device color space at the end of processing, if required
- RefPtr<SkImageFilter> filter;
- filter = transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceDeviceRGB);
- if (filter != noopFilter)
- filters->appendReferenceFilter(filter.get());
+ RefPtr<SkImageFilter> filter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
+ filters->appendReferenceFilter(filter.get());
}
return true;
}