summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm/qwasmdom.cpp
blob: ebb2dd4807a2f7d32635882a2e83d54d3311453f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "qwasmdom.h"

#include <QMimeData>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <QtGui/qimage.h>
#include <private/qstdweb_p.h>

#include <utility>

QT_BEGIN_NAMESPACE

namespace dom {

void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
{
    if (flag) {
        element["classList"].call<void>("add", emscripten::val(std::move(cssClassName)));
        return;
    }

    element["classList"].call<void>("remove", emscripten::val(std::move(cssClassName)));
}

QPointF mapPoint(emscripten::val source, emscripten::val target, const QPointF &point)
{
    const auto sourceBoundingRect =
            QRectF::fromDOMRect(source.call<emscripten::val>("getBoundingClientRect"));
    const auto targetBoundingRect =
            QRectF::fromDOMRect(target.call<emscripten::val>("getBoundingClientRect"));

    const auto offset = sourceBoundingRect.topLeft() - targetBoundingRect.topLeft();
    return point + offset;
}

void drawImageToWebImageDataArray(const QImage &sourceImage, emscripten::val destinationImageData,
                                  const QRect &sourceRect)
{
    Q_ASSERT_X(destinationImageData["constructor"]["name"].as<std::string>() == "ImageData",
               Q_FUNC_INFO, "The destination should be an ImageData instance");

    constexpr int BytesPerColor = 4;
    if (sourceRect.width() == sourceImage.width()) {
        // Copy a contiguous chunk of memory
        // ...............
        // OOOOOOOOOOOOOOO
        // OOOOOOOOOOOOOOO -> image data
        // OOOOOOOOOOOOOOO
        // ...............
        auto imageMemory = emscripten::typed_memory_view(sourceRect.width() * sourceRect.height()
                                                                 * BytesPerColor,
                                                         sourceImage.constScanLine(sourceRect.y()));
        destinationImageData["data"].call<void>(
                "set", imageMemory, sourceRect.y() * sourceImage.width() * BytesPerColor);
    } else {
        // Go through the scanlines manually to set the individual lines in bulk. This is
        // marginally less performant than the above.
        // ...............
        // ...OOOOOOOOO... r = 0  -> image data
        // ...OOOOOOOOO... r = 1  -> image data
        // ...OOOOOOOOO... r = 2  -> image data
        // ...............
        for (int row = 0; row < sourceRect.height(); ++row) {
            auto scanlineMemory =
                    emscripten::typed_memory_view(sourceRect.width() * BytesPerColor,
                                                  sourceImage.constScanLine(row + sourceRect.y())
                                                          + BytesPerColor * sourceRect.x());
            destinationImageData["data"].call<void>("set", scanlineMemory,
                                                    (sourceRect.y() + row) * sourceImage.width()
                                                                    * BytesPerColor
                                                            + sourceRect.x() * BytesPerColor);
        }
    }
}

} // namespace dom

QT_END_NAMESPACE