Skip to content

Instantly share code, notes, and snippets.

@balazs
Created July 6, 2012 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save balazs/3061148 to your computer and use it in GitHub Desktop.
Save balazs/3061148 to your computer and use it in GitHub Desktop.
diff --git a/Source/WebKit2/Shared/API/c/qt/WKImageQt.cpp b/Source/WebKit2/Shared/API/c/qt/WKImageQt.cpp
index d0975f6..bb7f89a 100644
--- a/Source/WebKit2/Shared/API/c/qt/WKImageQt.cpp
+++ b/Source/WebKit2/Shared/API/c/qt/WKImageQt.cpp
@@ -25,10 +25,27 @@
#include "ShareableBitmap.h"
#include "WKSharedAPICast.h"
#include "WebImage.h"
+#include <QPainter>
+#include <WebCore/IntSize.h>
+#include <WebCore/GraphicsContext.h>
+using namespace WebCore;
using namespace WebKit;
QImage WKImageCreateQImage(WKImageRef imageRef)
{
return toImpl(imageRef)->bitmap()->createQImage().copy();
}
+
+WKImageRef WKImageCreateFromQImage(QImage image)
+{
+ ASSERT(image.bytesPerLine() == image.width() * 4);
+
+ RefPtr<WebImage> webImage = WebImage::create(image.size(), static_cast<ImageOptions>(0));
+ if (!webImage->bitmap())
+ return 0;
+ OwnPtr<GraphicsContext> graphicsContext = webImage->bitmap()->createGraphicsContext();
+ QPainter* painter = graphicsContext->platformContext();
+ painter->drawImage(QPoint(0, 0), image);
+ return toAPI(webImage.release().leakRef());
+}
diff --git a/Source/WebKit2/Shared/API/c/qt/WKImageQt.h b/Source/WebKit2/Shared/API/c/qt/WKImageQt.h
index 1e5073a..d14c391 100644
--- a/Source/WebKit2/Shared/API/c/qt/WKImageQt.h
+++ b/Source/WebKit2/Shared/API/c/qt/WKImageQt.h
@@ -27,5 +27,6 @@
#include <WebKit2/WKImage.h>
WK_EXPORT QImage WKImageCreateQImage(WKImageRef image);
+WK_EXPORT WKImageRef WKImageCreateFromQImage(QImage image);
#endif
diff --git a/Tools/WebKitTestRunner/PlatformWebView.h b/Tools/WebKitTestRunner/PlatformWebView.h
index a8cf0d6..74ce123 100644
--- a/Tools/WebKitTestRunner/PlatformWebView.h
+++ b/Tools/WebKitTestRunner/PlatformWebView.h
@@ -29,10 +29,12 @@
#include <WebKit2/WKRetainPtr.h>
#if defined(BUILDING_QT__)
-class QQuickWebView;
-typedef QQuickWebView* PlatformWKView;
-class QQuickView;
-typedef QQuickView* PlatformWindow;
+class QRawWebView;
+typedef QRawWebView* PlatformWKView;
+namespace WTR {
+class QtView;
+}
+typedef WTR::QtView* PlatformWindow;
class QEventLoop;
#elif defined(__APPLE__) && __APPLE__
#if __OBJC__
diff --git a/Tools/WebKitTestRunner/Target.pri b/Tools/WebKitTestRunner/Target.pri
index b3b5c2c..1b7a7f9 100644
--- a/Tools/WebKitTestRunner/Target.pri
+++ b/Tools/WebKitTestRunner/Target.pri
@@ -27,6 +27,9 @@ DESTDIR = $${ROOT_BUILD_DIR}/bin
QT = core gui widgets network testlib quick quick-private webkit
+INCLUDEPATH += \
+ $${ROOT_WEBKIT_DIR}/Source/WebKit2/UIProcess/API/qt/raw
+
WEBKIT += wtf javascriptcore webkit2
DEFINES += USE_SYSTEM_MALLOC=1
diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp
index d5c0af6..9bbdc1d 100644
--- a/Tools/WebKitTestRunner/TestInvocation.cpp
+++ b/Tools/WebKitTestRunner/TestInvocation.cpp
@@ -263,7 +263,7 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
fputs("#EOF\n", stdout);
fflush(stdout);
fflush(stderr);
-
+
m_gotFinalMessage = true;
TestController::shared().notifyDone();
return;
diff --git a/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp b/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
index 0211df5..81dcbab 100644
--- a/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
+++ b/Tools/WebKitTestRunner/qt/PlatformWebViewQt.cpp
@@ -31,52 +31,163 @@
#include "qquickwebview_p.h"
#include <QCoreApplication>
+#include <QGuiApplication>
#include <QEventLoop>
-#include <QQmlProperty>
-#include <QtQuick/QQuickView>
+#include <QMatrix4x4>
+#include <QOpenGLContext>
+#include <QTimer>
+#include <QWindow>
+#include <WebKit2/WKImageQt.h>
+#include <qrawwebview_p.h>
#include <qwindowsysteminterface_qpa.h>
+#define WRITE_SNAPSHOT 1
+
+#if WRITE_SNAPSHOT
+#include <QImageWriter>
+#include <QFile>
+#endif
+
namespace WTR {
-class WrapperWindow : public QQuickView {
+class QtView : public QWindow, private QRawWebViewClient {
Q_OBJECT
public:
- WrapperWindow(QQuickWebView* view)
- : QQuickView(QUrl("data:text/plain,import QtQuick 2.0\nItem { objectName: 'root' }"))
- , m_view(view)
- {
- connect(this, SIGNAL(statusChanged(QQuickView::Status)), SLOT(handleStatusChanged(QQuickView::Status)));
- }
+ QtView(WKContextRef contextRef, WKPageGroupRef pageGroupRef);
+ ~QtView();
+
+ QImage createSnapshot();
+
+ QRawWebView* view() const { return m_view; }
+
+ // QRawWebViewClient
+ virtual void viewNeedsDisplay(const QRect&);
+ virtual void viewRenderedFrame();
+ virtual void viewRequestedCursorOverride(const QCursor&);
+ virtual void viewRequestedScroll(const QPoint&) { }
+ virtual void viewProcessCrashed() { }
+ virtual void viewProcessRelaunched() { }
+ virtual void viewContentSizeChanged(const QSize&) { }
+ virtual void doneWithKeyEvent(const QKeyEvent*, bool) { }
+ virtual void doneWithTouchEvent(const QTouchEvent*, bool) { }
+signals:
+ void didPaint();
+private:
+ QRawWebView* m_view;
+ QOpenGLContext* m_glContext;
+ bool m_isWaitingForSnapshot;
+};
+
+QtView::QtView(WKContextRef context, WKPageGroupRef pageGroup)
+ : m_isWaitingForSnapshot(false)
+{
+ const QSize initialSize(800, 600);
-private slots:
- void handleStatusChanged(QQuickView::Status status)
- {
- if (status != QQuickView::Ready)
- return;
+ setSurfaceType(OpenGLSurface);
+ setGeometry(0, 0, initialSize.width(), initialSize.height());
+ setWindowFlags(Qt::Window | Qt::WindowTitleHint);
+ create();
- setGeometry(0, 0, 800, 600);
+ m_glContext = new QOpenGLContext();
+ m_glContext->create();
+ m_glContext->makeCurrent(this);
+ glViewport(0, 0, size().width(), size().height());
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
- setResizeMode(QQuickView::SizeRootObjectToView);
- m_view->setParentItem(rootObject());
- QQmlProperty::write(m_view, "anchors.fill", qVariantFromValue(rootObject()));
+ m_view = new QRawWebView(context, pageGroup, this);
+ m_view->setSize(initialSize);
+ m_view->create();
+}
- QWindowSystemInterface::handleWindowActivated(this);
- m_view->page()->setFocus(true);
+QtView::~QtView()
+{
+ delete m_view;
+ delete m_glContext;
+}
+
+QImage QtView::createSnapshot()
+{
+ m_isWaitingForSnapshot = true;
+ m_view->update();
+
+ QEventLoop loop;
+ QTimer watchDogTimer;
+ QObject::connect(this, SIGNAL(didPaint()), &loop, SLOT(quit()));
+ QObject::connect(&watchDogTimer, SIGNAL(timeout()), &loop, SLOT(quit()));
+ watchDogTimer.singleShot(2000, &loop, SLOT(quit()));
+ loop.exec();
+
+ if (m_isWaitingForSnapshot) {
+ m_isWaitingForSnapshot = false;
+ fprintf(stderr, "did not paint\n");
+ return QImage();
}
-private:
- QQuickWebView* m_view;
-};
+ Q_ASSERT(QOpenGLContext::currentContext() == m_glContext);
+ QImage image(size(), QImage::Format_ARGB32_Premultiplied);
+ uchar* bits = const_cast<uchar*>(image.constBits());
+ glReadPixels(0, 0, size().width(), size().height(), GL_RGBA, GL_UNSIGNED_BYTE, bits);
+
+ // FIXME: should use a transformation matrix fot this.
+ QImage imageFlipped(size(), QImage::Format_ARGB32_Premultiplied);
+ uint height = image.size().height();
+ for (uint y = 0; y < height; ++y) {
+ const uchar* src = image.constScanLine(y);
+ const uchar* constDst = imageFlipped.constScanLine(height - 1 - y);
+ uchar* dst = const_cast<uchar*>(constDst);
+ memcpy(dst, src, image.bytesPerLine());
+ }
+
+#if WRITE_SNAPSHOT
+ static int c = 0;
+ QString fname("snapshot.%1.bmp");
+ QFile f(fname.arg(c++));
+ f.open(QFile::WriteOnly);
+ QImageWriter w(&f, "bmp");
+ w.write(imageFlipped);
+ f.close();
+#endif
+
+ return imageFlipped;
+}
+
+static inline QMatrix4x4 matrix()
+{
+ QMatrix4x4 mx;
+ //mx.rotate(180, 0, 1, 0);
+ return mx;
+}
+
+void QtView::viewNeedsDisplay(const QRect&)
+{
+ m_glContext->makeCurrent(this);
+ m_view->paint(matrix(), 1, 0);
+}
+
+void QtView::viewRenderedFrame()
+{
+ if (!m_isWaitingForSnapshot)
+ return;
-PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
- : m_view(new QQuickWebView(contextRef, pageGroupRef))
- , m_window(new WrapperWindow(m_view))
- , m_windowIsKey(true)
- , m_modalEventLoop(0)
+ m_glContext->makeCurrent(this);
+ m_view->paint(matrix(), 1, 0);
+ m_isWaitingForSnapshot = false;
+ emit didPaint();
+}
+
+void QtView::viewRequestedCursorOverride(const QCursor& cursor)
{
- QQuickWebViewExperimental experimental(m_view);
- experimental.setRenderToOffscreenBuffer(true);
- m_view->setAllowAnyHTTPSCertificateForLocalHost(true);
+ QGuiApplication::setOverrideCursor(cursor);
+}
+
+PlatformWebView::PlatformWebView(WKContextRef context, WKPageGroupRef pageGroup)
+ : m_modalEventLoop(0)
+{
+ m_window = new QtView(context, pageGroup);
+ m_view = m_window->view();
+
+ focus();
}
PlatformWebView::~PlatformWebView()
@@ -86,27 +197,21 @@ PlatformWebView::~PlatformWebView()
m_modalEventLoop->exit();
}
-void PlatformWebView::resizeTo(unsigned width, unsigned height)
+WKPageRef PlatformWebView::page()
{
- // If we do not have a platform window we will never get the necessary
- // resize event, so simulate it in that case to make sure the quickview is
- // resized to what the layout test expects.
- if (!m_window->handle()) {
- QRect newGeometry(m_window->x(), m_window->y(), width, height);
- QWindowSystemInterface::handleSynchronousGeometryChange(m_window, newGeometry);
- }
-
- m_window->resize(width, height);
+ return m_view->pageRef();
}
-WKPageRef PlatformWebView::page()
+void PlatformWebView::resizeTo(unsigned width, unsigned height)
{
- return m_view->pageRef();
+ m_view->setSize(QSize(width, height));
}
void PlatformWebView::focus()
{
- m_view->setFocus(Qt::OtherFocusReason);
+ m_view->setFocused(true);
+ m_view->setVisible(true);
+ m_view->setActive(true);
}
WKRect PlatformWebView::windowFrame()
@@ -123,6 +228,7 @@ WKRect PlatformWebView::windowFrame()
void PlatformWebView::setWindowFrame(WKRect wkRect)
{
m_window->setGeometry(wkRect.origin.x, wkRect.origin.y, wkRect.size.width, wkRect.size.height);
+ resizeTo(wkRect.size.width, wkRect.size.height);
}
bool PlatformWebView::sendEvent(QEvent* event)
@@ -149,9 +255,7 @@ void PlatformWebView::makeWebViewFirstResponder()
WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
{
- // FIXME: implement to capture pixels in the UI process,
- // which may be necessary to capture things like 3D transforms.
- return 0;
+ return WKImageCreateFromQImage(m_window->createSnapshot());
}
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp b/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp
index 01630d9..425ab16 100644
--- a/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp
+++ b/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#include "PlatformWebView.h"
+#include "TestController.h"
#include "TestInvocation.h"
#include <QBuffer>
@@ -67,7 +69,14 @@ void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef imageRef, WKArr
//FIXME: https://bugs.webkit.org/show_bug.cgi?id=68870
UNUSED_PARAM(repaintRects);
- QImage image = WKImageCreateQImage(imageRef);
+ PlatformWebView* webView = TestController::shared().mainWebView();
+ WKRetainPtr<WKImageRef> windowSnapshot = webView->windowSnapshotImage();
+ QImage image;
+ if (windowSnapshot)
+ image = WKImageCreateQImage(windowSnapshot.get());
+ else
+ image = WKImageCreateQImage(imageRef);
+
QCryptographicHash hash(QCryptographicHash::Md5);
for (unsigned row = 0; row < image.height(); ++row)
hash.addData(reinterpret_cast<const char*>(image.constScanLine(row)), image.bytesPerLine());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment