static void paintRepaintRectOverlay(CGContextRef context, WKImageRef image, WKArrayRef repaintRects) { WKSize imageSize = WKImageGetSize(image); CGContextSaveGState(context); // Using a transparency layer is easier than futzing with clipping. CGContextBeginTransparencyLayer(context, 0); // Flip the context. CGContextScaleCTM(context, 1, -1); CGContextTranslateCTM(context, 0, -imageSize.height); CGContextSetRGBFillColor(context, 0, 0, 0, static_cast<CGFloat>(0.66)); CGContextFillRect(context, CGRectMake(0, 0, imageSize.width, imageSize.height)); // Clear the repaint rects. size_t count = WKArrayGetSize(repaintRects); for (size_t i = 0; i < count; ++i) { WKRect rect = WKRectGetValue(static_cast<WKRectRef>(WKArrayGetItemAtIndex(repaintRects, i))); CGRect cgRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); CGContextClearRect(context, cgRect); } CGContextEndTransparencyLayer(context); CGContextRestoreGState(context); }
static void paintRepaintRectOverlay(cairo_surface_t* surface, WKArrayRef repaintRects) { cairo_t* context = cairo_create(surface); cairo_push_group(context); // Paint the gray mask over the original image. cairo_set_source_rgba(context, 0, 0, 0, 0.66); cairo_paint(context); // Paint transparent rectangles over the mask to show the repainted regions. cairo_set_source_rgba(context, 0, 0, 0, 0); cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); size_t count = WKArrayGetSize(repaintRects); for (size_t i = 0; i < count; ++i) { WKRect rect = WKRectGetValue(static_cast<WKRectRef>(WKArrayGetItemAtIndex(repaintRects, i))); cairo_rectangle(context, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); cairo_fill(context); } cairo_pop_group_to_source(context); cairo_paint(context); cairo_destroy(context); }
void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef imageRef, WKArrayRef repaintRects) { QImage image; if (PlatformWebView::windowShapshotEnabled()) { WKPageRef page = TestController::shared().mainWebView()->page(); WKPageForceRepaint(page, this, &forceRepaintDoneCallback); TestController::shared().runUntil(m_gotRepaint, TestController::ShortTimeout); if (m_gotRepaint) image = WKImageCreateQImage(TestController::shared().mainWebView()->windowSnapshotImage().get()); else { m_error = true; m_errorMessage = "Timed out waiting for repaint\n"; m_webProcessIsUnresponsive = true; return; } } else image = WKImageCreateQImage(imageRef); if (repaintRects) { QImage mask(image.size(), image.format()); mask.fill(QColor(0, 0, 0, 0.66 * 255)); QPainter maskPainter(&mask); maskPainter.setCompositionMode(QPainter::CompositionMode_Source); size_t count = WKArrayGetSize(repaintRects); for (size_t i = 0; i < count; ++i) { WKRect wkRect = WKRectGetValue(static_cast<WKRectRef>(WKArrayGetItemAtIndex(repaintRects, i))); QRectF rect(wkRect.origin.x, wkRect.origin.y, wkRect.size.width, wkRect.size.height); maskPainter.fillRect(rect, Qt::transparent); } QPainter painter(&image); painter.drawImage(image.rect(), mask); } QCryptographicHash hash(QCryptographicHash::Md5); for (unsigned row = 0; row < image.height(); ++row) hash.addData(reinterpret_cast<const char*>(image.constScanLine(row)), image.bytesPerLine()); QByteArray actualHash = hash.result().toHex(); ASSERT(actualHash.size() == 32); if (!compareActualHashToExpectedAndDumpResults(actualHash)) { image.setText("checksum", actualHash); dumpImage(image); } }