blob: db3c21c3f6423dd72a723307bd9444389530a697 [file] [log] [blame]
/*
* Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "FEDisplacementMapSoftwareApplier.h"
#include "FEDisplacementMap.h"
#include "Filter.h"
#include "GraphicsContext.h"
#include "PixelBuffer.h"
namespace WebCore {
FEDisplacementMapSoftwareApplier::FEDisplacementMapSoftwareApplier(FEDisplacementMap& effect)
: Base(effect)
{
ASSERT(m_effect.xChannelSelector() != CHANNEL_UNKNOWN);
ASSERT(m_effect.yChannelSelector() != CHANNEL_UNKNOWN);
}
int FEDisplacementMapSoftwareApplier::xChannelIndex() const
{
return m_effect.xChannelSelector() - 1;
}
int FEDisplacementMapSoftwareApplier::yChannelIndex() const
{
return m_effect.yChannelSelector() - 1;
}
bool FEDisplacementMapSoftwareApplier::apply(const Filter& filter, const FilterEffectVector& inputEffects)
{
FilterEffect* in = inputEffects[0].get();
FilterEffect* in2 = inputEffects[1].get();
auto destinationPixelBuffer = m_effect.pixelBufferResult(AlphaPremultiplication::Premultiplied);
if (!destinationPixelBuffer)
return false;
auto& destinationPixelArray = destinationPixelBuffer->data();
auto effectADrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in->absolutePaintRect());
auto inputPixelBuffer = in->getPixelBufferResult(AlphaPremultiplication::Premultiplied, effectADrawingRect);
auto effectBDrawingRect = m_effect.requestedRegionOfInputPixelBuffer(in2->absolutePaintRect());
// The calculations using the pixel values from ‘in2’ are performed using non-premultiplied color values.
auto displacementPixelBuffer = in2->getPixelBufferResult(AlphaPremultiplication::Unpremultiplied, effectBDrawingRect);
if (!inputPixelBuffer || !displacementPixelBuffer)
return false;
auto& inputImage = inputPixelBuffer->data();
auto& displacementImage = displacementPixelBuffer->data();
ASSERT(inputImage.length() == displacementImage.length());
IntSize paintSize = m_effect.absolutePaintRect().size();
FloatSize scale = filter.scaledByFilterScale({ m_effect.scale(), m_effect.scale() });
float scaleForColorX = scale.width() / 255.0;
float scaleForColorY = scale.height() / 255.0;
float scaledOffsetX = 0.5 - scale.width() * 0.5;
float scaledOffsetY = 0.5 - scale.height() * 0.5;
int displacementChannelX = xChannelIndex();
int displacementChannelY = yChannelIndex();
int rowBytes = paintSize.width() * 4;
for (int y = 0; y < paintSize.height(); ++y) {
int lineStartOffset = y * rowBytes;
for (int x = 0; x < paintSize.width(); ++x) {
int destinationIndex = lineStartOffset + x * 4;
int srcX = x + static_cast<int>(scaleForColorX * displacementImage.item(destinationIndex + displacementChannelX) + scaledOffsetX);
int srcY = y + static_cast<int>(scaleForColorY * displacementImage.item(destinationIndex + displacementChannelY) + scaledOffsetY);
unsigned* destinationPixelPtr = reinterpret_cast<unsigned*>(destinationPixelArray.data() + destinationIndex);
if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) {
*destinationPixelPtr = 0;
continue;
}
*destinationPixelPtr = *reinterpret_cast<unsigned*>(inputImage.data() + byteOffsetOfPixel(srcX, srcY, rowBytes));
}
}
return true;
}
} // namespace WebCore