Skip to content

Commit bae1097

Browse files
committed
[1131][AccCanvas] Fix the implementation of putImageData
1 parent 712afdd commit bae1097

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

Source/WebCore/platform/graphics/cairo/ImageBufferCairoGLSurfaceBackend.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "GLContextEGL.h"
77
#include "PixelBuffer.h"
8+
#include "PixelBufferConversion.h"
89
#include "TextureMapperPlatformLayerBuffer.h"
910
#include "TextureMapperPlatformLayerProxyGL.h"
1011
#include <cairo-gl.h>
@@ -246,17 +247,43 @@ RefPtr<PixelBuffer> ImageBufferCairoGLSurfaceBackend::getPixelBuffer(const Pixel
246247

247248
void ImageBufferCairoGLSurfaceBackend::putPixelBuffer(const PixelBuffer& pixelBuffer, const IntRect& srcRect, const IntPoint& destPoint, AlphaPremultiplication destFormat)
248249
{
249-
// Create a new image surface and put the data there. Then copy its contents to the original gl surface in the specified rect.
250-
auto surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, cairo_gl_surface_get_width(m_surfaces[0].get()), cairo_gl_surface_get_height(m_surfaces[0].get())));
251-
IntRect srcRectScaled = toBackendCoordinates(srcRect);
252-
IntPoint destPointScaled = toBackendCoordinates(destPoint);
253-
ImageBufferBackend::putPixelBuffer(pixelBuffer, srcRect, destPoint, destFormat, cairo_image_surface_get_data(surface.get()));
254-
cairo_surface_mark_dirty_rectangle(surface.get(), destPointScaled.x(), destPointScaled.y(), srcRectScaled.width(), srcRectScaled.height());
250+
auto sourceRectClipped = intersection({ IntPoint::zero(), pixelBuffer.size() }, srcRect);
251+
auto destinationRect = sourceRectClipped;
252+
destinationRect.moveBy(destPoint);
253+
254+
if (srcRect.x() < 0)
255+
destinationRect.setX(destinationRect.x() - srcRect.x());
256+
257+
if (srcRect.y() < 0)
258+
destinationRect.setY(destinationRect.y() - srcRect.y());
259+
260+
destinationRect.intersect(backendRect());
261+
sourceRectClipped.setSize(destinationRect.size());
262+
263+
// Create an intermediate surface with the size of the rectangle that we need to copy. Then we can use convertImagePixels
264+
// to properly convert and copy the relevant pixels into this intermediate surface. Once this is done, use cairo to paint the
265+
// intermediate surface into the buffer surface in the appropriate position.
266+
auto surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, destinationRect.width(), destinationRect.height()));
267+
268+
ConstPixelBufferConversionView source {
269+
pixelBuffer.format(),
270+
static_cast<unsigned>(4 * pixelBuffer.size().width()),
271+
pixelBuffer.bytes() + sourceRectClipped.y() * source.bytesPerRow + sourceRectClipped.x() * 4
272+
};
273+
274+
PixelBufferConversionView destination {
275+
{ destFormat, pixelFormat(), colorSpace() },
276+
static_cast<unsigned>(4 * destinationRect.width()),
277+
static_cast<uint8_t*>(cairo_image_surface_get_data(surface.get()))
278+
};
279+
280+
convertImagePixels(source, destination, destinationRect.size());
281+
cairo_surface_mark_dirty_rectangle(surface.get(), 0, 0, destinationRect.width(), destinationRect.height());
255282

256283
auto cr = adoptRef(cairo_create(m_surfaces[0].get()));
257284
cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE);
258-
cairo_set_source_surface(cr.get(), surface.get(), destPointScaled.x(), destPointScaled.y());
259-
cairo_rectangle(cr.get(), destPointScaled.x(), destPointScaled.y(), srcRectScaled.width(), srcRectScaled.height());
285+
cairo_set_source_surface(cr.get(), surface.get(), destinationRect.x(), destinationRect.y());
286+
cairo_rectangle(cr.get(), destinationRect.x(), destinationRect.y(), destinationRect.width(), destinationRect.height());
260287
cairo_fill(cr.get());
261288
}
262289

0 commit comments

Comments
 (0)