[Libreoffice-commits] core.git: configure.ac vcl/qt5 wasm-qt/CustomTarget_wasm-qt5-mandelbrot_moc.mk wasm-qt/Executable_wasm-qt5-mandelbrot.mk wasm-qt/Makefile wasm-qt/Module_wasm-qt.mk wasm-qt/README wasm-qt/source xmlsecurity/Library_xmlsecurity.mk

Jan-Marek Glogowski (via logerrit) logerrit at kemper.freedesktop.org
Wed May 5 19:16:08 UTC 2021


 configure.ac                                       |   27 ++
 vcl/qt5/Qt5Instance.cxx                            |    9 
 vcl/qt5/Qt5MainWindow.cxx                          |    2 
 wasm-qt/CustomTarget_wasm-qt5-mandelbrot_moc.mk    |   37 +++
 wasm-qt/Executable_wasm-qt5-mandelbrot.mk          |   32 ++
 wasm-qt/Makefile                                   |   13 +
 wasm-qt/Module_wasm-qt.mk                          |   20 +
 wasm-qt/README                                     |    1 
 wasm-qt/source/qt5-mandelbrot/main.cxx             |   66 +++++
 wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.cxx |  228 ++++++++++++++++++++
 wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.h   |   91 ++++++++
 wasm-qt/source/qt5-mandelbrot/renderthread.cxx     |  232 +++++++++++++++++++++
 wasm-qt/source/qt5-mandelbrot/renderthread.h       |   97 ++++++++
 xmlsecurity/Library_xmlsecurity.mk                 |    2 
 14 files changed, 853 insertions(+), 4 deletions(-)

New commits:
commit f90c68316c622971706568303a025bbc58351df3
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Fri Apr 23 14:03:31 2021 +0200
Commit:     Thorsten Behrens <thorsten.behrens at allotropia.de>
CommitDate: Wed May 5 21:15:22 2021 +0200

    WASM: add Emscripten demo application
    
    Change-Id: I31297142761255b1f357fc9677a644b7a93c921a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111128
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behrens at allotropia.de>

diff --git a/configure.ac b/configure.ac
index e5ce5560c661..9a9e42031ae1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12528,10 +12528,18 @@ then
     fi
 
     qt5_test_include="QtWidgets/qapplication.h"
-    qt5_test_library="libQt5Widgets.so"
+    if test "$_os" = "Emscripten"; then
+        qt5_test_library="libQt5Widgets.a"
+    else
+        qt5_test_library="libQt5Widgets.so"
+    fi
 
     dnl Check for qmake5
-    AC_PATH_PROGS( QMAKE5, [qmake-qt5 qmake], no, [$QT5DIR/bin:$PATH])
+    if test -n "$QT5DIR"; then
+        AC_PATH_PROG(QMAKE5, [qmake], no, [$QT5DIR/bin])
+    else
+        AC_PATH_PROGS(QMAKE5, [qmake-qt5 qmake], no)
+    fi
     if test "$QMAKE5" = "no"; then
         AC_MSG_ERROR([Qmake not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
     else
@@ -12550,6 +12558,8 @@ then
 
     qt5_incdirs="`$QMAKE5 -query QT_INSTALL_HEADERS` $qt5_incdirs"
     qt5_libdirs="`$QMAKE5 -query QT_INSTALL_LIBS` $qt5_libdirs"
+    qt5_platformsdir="`$QMAKE5 -query QT_INSTALL_PLUGINS`/platforms"
+    QT5_PLATFORMS_SRCDIR="$qt5_platformsdir"
 
     AC_MSG_CHECKING([for Qt5 headers])
     qt5_incdir="no"
@@ -12585,9 +12595,21 @@ then
         AC_MSG_ERROR([Qt5 libraries not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
     fi
 
+    if test "$_os" = "Emscripten"; then
+        if test ! -f "$QT5_PLATFORMS_SRCDIR"/wasm_shell.html ; then
+            QT5_PLATFORMS_SRCDIR="${QT5_PLATFORMS_SRCDIR/plugins/src\/plugins}/wasm"
+        fi
+	if test ! -f "${qt5_platformsdir}"/libqwasm.a -o ! -f "$QT5_PLATFORMS_SRCDIR"/wasm_shell.html; then
+            AC_MSG_ERROR([No Qt5 WASM QPA plugin found in ${qt5_platformsdir} or ${QT5_PLATFORMS_SRCDIR}])
+        fi
+    fi
+
     QT5_CFLAGS="-I$qt5_incdir -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT -DQT_NO_VERSION_TAGGING"
     QT5_CFLAGS=$(printf '%s' "$QT5_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g")
     QT5_LIBS="-L$qt5_libdir -lQt5Core -lQt5Gui -lQt5Widgets -lQt5Network"
+    if test "$_os" = "Emscripten"; then
+        QT5_LIBS="$QT5_LIBS -lqtpcre2 -lQt5EventDispatcherSupport -lQt5FontDatabaseSupport -L${qt5_platformsdir} -lqwasm"
+    fi
 
     if test "$USING_X11" = TRUE; then
         PKG_CHECK_MODULES(QT5_XCB,[xcb],,[AC_MSG_ERROR([XCB not found, which is needed for correct app grouping in X11.])])
@@ -12627,6 +12649,7 @@ AC_SUBST(MOC5)
 AC_SUBST(QT5_GOBJECT_CFLAGS)
 AC_SUBST(QT5_GOBJECT_LIBS)
 AC_SUBST(QT5_HAVE_GOBJECT)
+AC_SUBST(QT5_PLATFORMS_SRCDIR)
 
 dnl ===================================================================
 dnl KF5 Integration
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index f0c1f56f6690..bf8d52961960 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -54,6 +54,11 @@
 #include <mutex>
 #include <condition_variable>
 
+#ifdef EMSCRIPTEN
+#include <QtCore/QtPlugin>
+Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
+#endif
+
 namespace
 {
 /// TODO: not much Qt5 specific here? could be generalised, esp. for OSX...
@@ -427,7 +432,7 @@ OUString Qt5Instance::GetConnectionIdentifier() { return OUString(); }
 
 void Qt5Instance::AddToRecentDocumentList(const OUString&, const OUString&, const OUString&) {}
 
-OpenGLContext* Qt5Instance::CreateOpenGLContext() { return new Qt5OpenGLContext; }
+OpenGLContext* Qt5Instance::CreateOpenGLContext() { return nullptr; }
 
 bool Qt5Instance::IsMainThread() const
 {
@@ -570,7 +575,7 @@ void* Qt5Instance::CreateGStreamerSink(const SystemChildWindow* pWindow)
 
     return pVideosink;
 #else
-    (void*)pWindow;
+    Q_UNUSED(pWindow);
     return nullptr;
 #endif
 }
diff --git a/vcl/qt5/Qt5MainWindow.cxx b/vcl/qt5/Qt5MainWindow.cxx
index 45d726ba22be..89879864a9bc 100644
--- a/vcl/qt5/Qt5MainWindow.cxx
+++ b/vcl/qt5/Qt5MainWindow.cxx
@@ -19,7 +19,9 @@ Qt5MainWindow::Qt5MainWindow(Qt5Frame& rFrame, Qt::WindowFlags f)
     : QMainWindow(nullptr, f)
     , m_rFrame(rFrame)
 {
+#ifndef EMSCRIPTEN
     QAccessible::installFactory(Qt5AccessibleWidget::customFactory);
+#endif
 }
 
 void Qt5MainWindow::closeEvent(QCloseEvent* pEvent)
diff --git a/wasm-qt/CustomTarget_wasm-qt5-mandelbrot_moc.mk b/wasm-qt/CustomTarget_wasm-qt5-mandelbrot_moc.mk
new file mode 100644
index 000000000000..6267db3f5b8d
--- /dev/null
+++ b/wasm-qt/CustomTarget_wasm-qt5-mandelbrot_moc.mk
@@ -0,0 +1,37 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,wasm-qt/qt5-mandelbrot))
+
+$(call gb_CustomTarget_get_target,wasm-qt/qt5-mandelbrot) : \
+	$(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/renderthread.moc \
+	$(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/mandelbrotwidget.moc \
+
+qt5_mandelbrot_MOCDEFS_H := $(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/moc_predefs.h
+qt5_mandelbrot_MOCDEFS_CXX := $(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/moc_dummy.cxx
+qt5_mandelbrot_WORKDIR :=  $(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/.dir
+
+$(qt5_mandelbrot_MOCDEFS_CXX): | $(qt5_mandelbrot_WORKDIR)
+	touch $@
+
+$(qt5_mandelbrot_MOCDEFS_H): $(qt5_mandelbrot_MOCDEFS_CXX) | $(qt5_mandelbrot_WORKDIR)
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),CXX,1)
+	$(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),CXX)
+	$(CXX) -pipe -O2 -std=gnu++11 -fno-exceptions $(gb_EMSCRIPTEN_CPPFLAGS) -dM -E -o $@ $<
+	$(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MOC)
+
+$(call gb_CustomTarget_get_workdir,wasm-qt/qt5-mandelbrot)/%.moc : \
+		$(SRCDIR)/wasm-qt/source/qt5-mandelbrot/%.h \
+		$(qt5_mandelbrot_MOCDEFS_H) | $(qt5_mandelbrot_WORKDIR)
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1)
+	$(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),MOC)
+	$(MOC5) --include $(qt5_mandelbrot_MOCDEFS_H) $(gb_EMSCRIPTEN_QTDEFS) $< -o $@
+	$(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MOC)
+
+# vim: set noet sw=4:
diff --git a/wasm-qt/Executable_wasm-qt5-mandelbrot.mk b/wasm-qt/Executable_wasm-qt5-mandelbrot.mk
new file mode 100644
index 000000000000..040fad441219
--- /dev/null
+++ b/wasm-qt/Executable_wasm-qt5-mandelbrot.mk
@@ -0,0 +1,32 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,wasm-qt5-mandelbrot))
+
+$(eval $(call gb_Executable_use_custom_headers,wasm-qt5-mandelbrot,wasm-qt/qt5-mandelbrot))
+
+$(eval $(call gb_Executable_use_externals,wasm-qt5-mandelbrot,\
+    graphite \
+    freetype \
+    harfbuzz \
+    libpng \
+    qt5 \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,wasm-qt5-mandelbrot,\
+    wasm-qt/source/qt5-mandelbrot/main \
+    wasm-qt/source/qt5-mandelbrot/mandelbrotwidget \
+    wasm-qt/source/qt5-mandelbrot/renderthread \
+))
+
+$(eval $(call gb_Executable_add_defs,wasm-qt5-mandelbrot,\
+    -DVCL_INTERNALS \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm-qt/Makefile b/wasm-qt/Makefile
new file mode 100644
index 000000000000..0c6f47b1790f
--- /dev/null
+++ b/wasm-qt/Makefile
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm-qt/Module_wasm-qt.mk b/wasm-qt/Module_wasm-qt.mk
new file mode 100644
index 000000000000..8e86df4e8baa
--- /dev/null
+++ b/wasm-qt/Module_wasm-qt.mk
@@ -0,0 +1,20 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_Module_Module,wasm-qt))
+
+ifeq ($(OS),EMSCRIPTEN)
+
+$(eval $(call gb_Module_add_targets,wasm-qt,\
+    CustomTarget_wasm-qt5-mandelbrot_moc \
+    Executable_wasm-qt5-mandelbrot \
+))
+
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm-qt/README b/wasm-qt/README
new file mode 100644
index 000000000000..a23bd6a45ea9
--- /dev/null
+++ b/wasm-qt/README
@@ -0,0 +1 @@
+See /README.wasm
diff --git a/wasm-qt/source/qt5-mandelbrot/main.cxx b/wasm-qt/source/qt5-mandelbrot/main.cxx
new file mode 100644
index 000000000000..037c63153cf2
--- /dev/null
+++ b/wasm-qt/source/qt5-mandelbrot/main.cxx
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mandelbrotwidget.h"
+
+#include <QtWidgets/QApplication>
+#include <QtCore/QtPlugin>
+
+Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
+
+int main(int argc, char* argv[])
+{
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+    QApplication app(argc, argv);
+    MandelbrotWidget widget;
+    widget.show();
+    return app.exec();
+}
diff --git a/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.cxx b/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.cxx
new file mode 100644
index 000000000000..5886dd2664c0
--- /dev/null
+++ b/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.cxx
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mandelbrotwidget.h"
+#include "mandelbrotwidget.moc"
+
+#include <QtGui/QPainter>
+#include <QtGui/QKeyEvent>
+
+#include <math.h>
+
+const double DefaultCenterX = -0.637011;
+const double DefaultCenterY = -0.0395159;
+const double DefaultScale = 0.00403897;
+
+const double ZoomInFactor = 0.8;
+const double ZoomOutFactor = 1 / ZoomInFactor;
+const int ScrollStep = 20;
+
+MandelbrotWidget::MandelbrotWidget(QWidget* parent)
+    : QWidget(parent)
+    , centerX(DefaultCenterX)
+    , centerY(DefaultCenterY)
+    , pixmapScale(DefaultScale)
+    , curScale(DefaultScale)
+{
+    connect(&thread, &RenderThread::renderedImage, this, &MandelbrotWidget::updatePixmap);
+
+    setWindowTitle(tr("Mandelbrot"));
+#if QT_CONFIG(cursor)
+    setCursor(Qt::CrossCursor);
+#endif
+    resize(550, 400);
+}
+
+void MandelbrotWidget::paintEvent(QPaintEvent* /* event */)
+{
+    QPainter painter(this);
+    painter.fillRect(rect(), Qt::black);
+
+    if (pixmap.isNull())
+    {
+        painter.setPen(Qt::white);
+        painter.drawText(rect(), Qt::AlignCenter, tr("Rendering initial image, please wait..."));
+        return;
+    }
+
+    if (qFuzzyCompare(curScale, pixmapScale))
+    {
+        painter.drawPixmap(pixmapOffset, pixmap);
+    }
+    else
+    {
+        auto previewPixmap = qFuzzyCompare(pixmap.devicePixelRatioF(), qreal(1))
+                                 ? pixmap
+                                 : pixmap.scaled(pixmap.size() / pixmap.devicePixelRatioF(),
+                                                 Qt::KeepAspectRatio, Qt::SmoothTransformation);
+        double scaleFactor = pixmapScale / curScale;
+        int newWidth = int(previewPixmap.width() * scaleFactor);
+        int newHeight = int(previewPixmap.height() * scaleFactor);
+        int newX = pixmapOffset.x() + (previewPixmap.width() - newWidth) / 2;
+        int newY = pixmapOffset.y() + (previewPixmap.height() - newHeight) / 2;
+
+        painter.save();
+        painter.translate(newX, newY);
+        painter.scale(scaleFactor, scaleFactor);
+
+        QRectF exposed = painter.transform().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
+        painter.drawPixmap(exposed, previewPixmap, exposed);
+        painter.restore();
+    }
+
+    QString text = tr("Use mouse wheel or the '+' and '-' keys to zoom. "
+                      "Press and hold left mouse button to scroll.");
+    QFontMetrics metrics = painter.fontMetrics();
+    int textWidth = metrics.horizontalAdvance(text);
+
+    painter.setPen(Qt::NoPen);
+    painter.setBrush(QColor(0, 0, 0, 127));
+    painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5);
+    painter.setPen(Qt::white);
+    painter.drawText((width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text);
+}
+
+void MandelbrotWidget::resizeEvent(QResizeEvent* /* event */)
+{
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
+
+void MandelbrotWidget::keyPressEvent(QKeyEvent* event)
+{
+    switch (event->key())
+    {
+        case Qt::Key_Plus:
+            zoom(ZoomInFactor);
+            break;
+        case Qt::Key_Minus:
+            zoom(ZoomOutFactor);
+            break;
+        case Qt::Key_Left:
+            scroll(-ScrollStep, 0);
+            break;
+        case Qt::Key_Right:
+            scroll(+ScrollStep, 0);
+            break;
+        case Qt::Key_Down:
+            scroll(0, -ScrollStep);
+            break;
+        case Qt::Key_Up:
+            scroll(0, +ScrollStep);
+            break;
+        default:
+            QWidget::keyPressEvent(event);
+    }
+}
+
+#if QT_CONFIG(wheelevent)
+void MandelbrotWidget::wheelEvent(QWheelEvent* event)
+{
+    const int numDegrees = event->angleDelta().y() / 8;
+    const double numSteps = numDegrees / double(15);
+    zoom(pow(ZoomInFactor, numSteps));
+}
+#endif
+
+void MandelbrotWidget::mousePressEvent(QMouseEvent* event)
+{
+    if (event->button() == Qt::LeftButton)
+        lastDragPos = event->pos();
+}
+
+void MandelbrotWidget::mouseMoveEvent(QMouseEvent* event)
+{
+    if (event->buttons() & Qt::LeftButton)
+    {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = event->pos();
+        update();
+    }
+}
+
+void MandelbrotWidget::mouseReleaseEvent(QMouseEvent* event)
+{
+    if (event->button() == Qt::LeftButton)
+    {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = QPoint();
+
+        const auto pixmapSize = pixmap.size() / pixmap.devicePixelRatioF();
+        int deltaX = (width() - pixmapSize.width()) / 2 - pixmapOffset.x();
+        int deltaY = (height() - pixmapSize.height()) / 2 - pixmapOffset.y();
+        scroll(deltaX, deltaY);
+    }
+}
+
+void MandelbrotWidget::updatePixmap(const QImage& image, double scaleFactor)
+{
+    if (!lastDragPos.isNull())
+        return;
+
+    pixmap = QPixmap::fromImage(image);
+    pixmapOffset = QPoint();
+    lastDragPos = QPoint();
+    pixmapScale = scaleFactor;
+    update();
+}
+
+void MandelbrotWidget::zoom(double zoomFactor)
+{
+    curScale *= zoomFactor;
+    update();
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
+
+void MandelbrotWidget::scroll(int deltaX, int deltaY)
+{
+    centerX += deltaX * curScale;
+    centerY += deltaY * curScale;
+    update();
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
diff --git a/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.h b/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.h
new file mode 100644
index 000000000000..72e95568b522
--- /dev/null
+++ b/wasm-qt/source/qt5-mandelbrot/mandelbrotwidget.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtGui/QPixmap>
+#include <QtWidgets/QWidget>
+
+#include "renderthread.h"
+
+class MandelbrotWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    MandelbrotWidget(QWidget* parent = nullptr);
+
+protected:
+    void paintEvent(QPaintEvent* event) override;
+    void resizeEvent(QResizeEvent* event) override;
+    void keyPressEvent(QKeyEvent* event) override;
+#if QT_CONFIG(wheelevent)
+    void wheelEvent(QWheelEvent* event) override;
+#endif
+    void mousePressEvent(QMouseEvent* event) override;
+    void mouseMoveEvent(QMouseEvent* event) override;
+    void mouseReleaseEvent(QMouseEvent* event) override;
+
+private slots:
+    void updatePixmap(const QImage& image, double scaleFactor);
+    void zoom(double zoomFactor);
+
+private:
+    void scroll(int deltaX, int deltaY);
+
+    RenderThread thread;
+    QPixmap pixmap;
+    QPoint pixmapOffset;
+    QPoint lastDragPos;
+    double centerX;
+    double centerY;
+    double pixmapScale;
+    double curScale;
+};
diff --git a/wasm-qt/source/qt5-mandelbrot/renderthread.cxx b/wasm-qt/source/qt5-mandelbrot/renderthread.cxx
new file mode 100644
index 000000000000..398e43ded15d
--- /dev/null
+++ b/wasm-qt/source/qt5-mandelbrot/renderthread.cxx
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderthread.h"
+#include "renderthread.moc"
+
+#include <QtGui/QImage>
+#include <cmath>
+
+RenderThread::RenderThread(QObject* parent)
+    : QThread(parent)
+{
+    for (int i = 0; i < ColormapSize; ++i)
+        m_colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
+}
+
+RenderThread::~RenderThread()
+{
+    m_mutex.lock();
+    m_abort = true;
+    m_condition.wakeOne();
+    m_mutex.unlock();
+
+    wait();
+}
+
+void RenderThread::render(double centerX, double centerY, double scaleFactor, QSize resultSize,
+                          double devicePixelRatio)
+{
+    QMutexLocker locker(&m_mutex);
+
+    m_centerX = centerX;
+    m_centerY = centerY;
+    m_scaleFactor = scaleFactor;
+    m_devicePixelRatio = devicePixelRatio;
+    m_resultSize = resultSize;
+
+    if (!isRunning())
+    {
+        start(LowPriority);
+    }
+    else
+    {
+        m_restart = true;
+        m_condition.wakeOne();
+    }
+}
+
+void RenderThread::run()
+{
+    forever
+    {
+        m_mutex.lock();
+        const double devicePixelRatio = m_devicePixelRatio;
+        const QSize resultSize = m_resultSize * devicePixelRatio;
+        const double requestedScaleFactor = m_scaleFactor;
+        const double scaleFactor = requestedScaleFactor / devicePixelRatio;
+        const double centerX = m_centerX;
+        const double centerY = m_centerY;
+        m_mutex.unlock();
+
+        int halfWidth = resultSize.width() / 2;
+        int halfHeight = resultSize.height() / 2;
+        QImage image(resultSize, QImage::Format_RGB32);
+        image.setDevicePixelRatio(devicePixelRatio);
+
+        const int NumPasses = 8;
+        int pass = 0;
+        while (pass < NumPasses)
+        {
+            const int MaxIterations = (1 << (2 * pass + 6)) + 32;
+            const int Limit = 4;
+            bool allBlack = true;
+
+            for (int y = -halfHeight; y < halfHeight; ++y)
+            {
+                if (m_restart)
+                    break;
+                if (m_abort)
+                    return;
+
+                auto scanLine = reinterpret_cast<uint*>(image.scanLine(y + halfHeight));
+                const double ay = centerY + (y * scaleFactor);
+
+                for (int x = -halfWidth; x < halfWidth; ++x)
+                {
+                    const double ax = centerX + (x * scaleFactor);
+                    double a1 = ax;
+                    double b1 = ay;
+                    int numIterations = 0;
+
+                    do
+                    {
+                        ++numIterations;
+                        const double a2 = (a1 * a1) - (b1 * b1) + ax;
+                        const double b2 = (2 * a1 * b1) + ay;
+                        if ((a2 * a2) + (b2 * b2) > Limit)
+                            break;
+
+                        ++numIterations;
+                        a1 = (a2 * a2) - (b2 * b2) + ax;
+                        b1 = (2 * a2 * b2) + ay;
+                        if ((a1 * a1) + (b1 * b1) > Limit)
+                            break;
+                    } while (numIterations < MaxIterations);
+
+                    if (numIterations < MaxIterations)
+                    {
+                        *scanLine++ = m_colormap[numIterations % ColormapSize];
+                        allBlack = false;
+                    }
+                    else
+                    {
+                        *scanLine++ = qRgb(0, 0, 0);
+                    }
+                }
+            }
+
+            if (allBlack && pass == 0)
+            {
+                pass = 4;
+            }
+            else
+            {
+                if (!m_restart)
+                    emit renderedImage(image, requestedScaleFactor);
+                ++pass;
+            }
+        }
+
+        m_mutex.lock();
+        if (!m_restart)
+            m_condition.wait(&m_mutex);
+        m_restart = false;
+        m_mutex.unlock();
+    }
+}
+
+uint RenderThread::rgbFromWaveLength(double wave)
+{
+    double r = 0;
+    double g = 0;
+    double b = 0;
+
+    if (wave >= 380.0 && wave <= 440.0)
+    {
+        r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
+        b = 1.0;
+    }
+    else if (wave >= 440.0 && wave <= 490.0)
+    {
+        g = (wave - 440.0) / (490.0 - 440.0);
+        b = 1.0;
+    }
+    else if (wave >= 490.0 && wave <= 510.0)
+    {
+        g = 1.0;
+        b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
+    }
+    else if (wave >= 510.0 && wave <= 580.0)
+    {
+        r = (wave - 510.0) / (580.0 - 510.0);
+        g = 1.0;
+    }
+    else if (wave >= 580.0 && wave <= 645.0)
+    {
+        r = 1.0;
+        g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
+    }
+    else if (wave >= 645.0 && wave <= 780.0)
+    {
+        r = 1.0;
+    }
+
+    double s = 1.0;
+    if (wave > 700.0)
+        s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
+    else if (wave < 420.0)
+        s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);
+
+    r = std::pow(r * s, 0.8);
+    g = std::pow(g * s, 0.8);
+    b = std::pow(b * s, 0.8);
+    return qRgb(int(r * 255), int(g * 255), int(b * 255));
+}
diff --git a/wasm-qt/source/qt5-mandelbrot/renderthread.h b/wasm-qt/source/qt5-mandelbrot/renderthread.h
new file mode 100644
index 000000000000..16c0d86fd46c
--- /dev/null
+++ b/wasm-qt/source/qt5-mandelbrot/renderthread.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore/QMutex>
+#include <QtCore/QSize>
+#include <QtCore/QThread>
+#include <QtCore/QWaitCondition>
+
+QT_BEGIN_NAMESPACE
+class QImage;
+QT_END_NAMESPACE
+
+class RenderThread : public QThread
+{
+    Q_OBJECT
+
+public:
+    RenderThread(QObject* parent = nullptr);
+    ~RenderThread();
+
+    void render(double centerX, double centerY, double scaleFactor, QSize resultSize,
+                double devicePixelRatio);
+
+signals:
+    void renderedImage(const QImage& image, double scaleFactor);
+
+protected:
+    void run() override;
+
+private:
+    static uint rgbFromWaveLength(double wave);
+
+    QMutex m_mutex;
+    QWaitCondition m_condition;
+    double m_centerX;
+    double m_centerY;
+    double m_scaleFactor;
+    double m_devicePixelRatio;
+    QSize m_resultSize;
+    bool m_restart = false;
+    bool m_abort = false;
+
+    enum
+    {
+        ColormapSize = 512
+    };
+    uint m_colormap[ColormapSize];
+};
diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
index f50140edb303..1e974297f43e 100644
--- a/xmlsecurity/Library_xmlsecurity.mk
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -91,6 +91,7 @@ $(eval $(call gb_Library_use_system_win32_libs,xmlsecurity,\
 ))
 else
 ifneq (,$(filter DESKTOP,$(BUILD_TYPE))$(filter ANDROID,$(OS)))
+ifeq (TRUE,$(ENABLE_NSS))
 $(eval $(call gb_Library_add_defs,xmlsecurity,\
     -DXMLSEC_CRYPTO_NSS \
 ))
@@ -98,6 +99,7 @@ $(eval $(call gb_Library_use_externals,xmlsecurity,\
     nss3 \
     plc4 \
 ))
+endif
 endif # BUILD_TYPE=DESKTOP
 endif
 


More information about the Libreoffice-commits mailing list