blob: c2bac67d80c657b34aea0fa9c1047f1597f87d30 [file] [log] [blame]
/*
* Copyright (C) 2011,2014 Igalia S.L.
* Copyright (C) 2011 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "BackingStoreBackendCairoImpl.h"
#if USE(CAIRO)
#include "CairoUtilities.h"
namespace WebCore {
static const Seconds scrollHysteresisDuration { 300_ms };
static RefPtr<cairo_surface_t> createCairoImageSurfaceWithFastMalloc(const IntSize& size, double deviceScaleFactor)
{
static cairo_user_data_key_t s_surfaceDataKey;
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size.width());
auto* surfaceData = fastZeroedMalloc(size.height() * stride);
RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(static_cast<unsigned char*>(surfaceData), CAIRO_FORMAT_ARGB32, size.width(), size.height(), stride));
cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, surfaceData, [](void* data) { fastFree(data); });
cairo_surface_set_device_scale(surface.get(), deviceScaleFactor, deviceScaleFactor);
return surface;
}
BackingStoreBackendCairoImpl::BackingStoreBackendCairoImpl(const IntSize& size, float deviceScaleFactor)
: BackingStoreBackendCairo(size)
, m_scrolledHysteresis([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_scrollSurface = nullptr; }, scrollHysteresisDuration)
{
IntSize scaledSize = m_size;
scaledSize.scale(deviceScaleFactor);
m_surface = createCairoImageSurfaceWithFastMalloc(scaledSize, deviceScaleFactor);
}
BackingStoreBackendCairoImpl::~BackingStoreBackendCairoImpl() = default;
void BackingStoreBackendCairoImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
{
IntRect targetRect = scrollRect;
targetRect.move(scrollOffset);
targetRect.intersect(scrollRect);
if (targetRect.isEmpty())
return;
if (!m_scrollSurface) {
IntSize size(cairo_image_surface_get_width(m_surface.get()), cairo_image_surface_get_height(m_surface.get()));
double xScale, yScale;
cairo_surface_get_device_scale(m_surface.get(), &xScale, &yScale);
ASSERT(xScale == yScale);
m_scrollSurface = createCairoImageSurfaceWithFastMalloc(size, xScale);
}
copyRectFromOneSurfaceToAnother(m_surface.get(), m_scrollSurface.get(), scrollOffset, targetRect);
copyRectFromOneSurfaceToAnother(m_scrollSurface.get(), m_surface.get(), IntSize(), targetRect);
m_scrolledHysteresis.impulse();
}
} // namespace WebCore
#endif // USE(CAIRO)