Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Qt6 and MSVC 2019 Support #16611

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

if(MBGL_WITH_QT)
find_package(Qt5Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
endif()
Expand Down
3 changes: 3 additions & 0 deletions include/mbgl/style/expression/expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class Result : private variant<EvaluationError, T> {

Result() = default;

template <typename U>
VARIANT_INLINE Result(U&& val) : variant<EvaluationError, T>(val) {}

explicit operator bool () const {
return this->template is<T>();
}
Expand Down
3 changes: 3 additions & 0 deletions include/mbgl/style/expression/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ using ValueBase = variant<NullValue,
struct Value : ValueBase {
using ValueBase::ValueBase;

template <typename T>
VARIANT_INLINE Value(T&& val) : ValueBase(val) {}

// Javascript's Number.MAX_SAFE_INTEGER
static uint64_t maxSafeInteger() { return 9007199254740991ULL; }

Expand Down
32 changes: 16 additions & 16 deletions include/mbgl/util/enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ class Enum {
static optional<T> toEnum(const std::string&);
};

#define MBGL_DEFINE_ENUM(T, values...) \
\
static const constexpr std::pair<const T, const char *> T##_names[] = values; \
\
template <> \
const char * Enum<T>::toString(T t) { \
auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
[&] (const auto& v) { return t == v.first; }); \
assert(it != std::end(T##_names)); return it->second; \
} \
\
template <> \
optional<T> Enum<T>::toEnum(const std::string& s) { \
auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
[&] (const auto& v) { return s == v.second; }); \
return it == std::end(T##_names) ? optional<T>() : it->first; \
#define MBGL_DEFINE_ENUM(T, ...) \
\
static const constexpr std::pair<const T, const char *> T##_names[] = __VA_ARGS__; \
\
template <> \
const char * Enum<T>::toString(T t) { \
auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
[&] (const auto& v) { return t == v.first; }); \
assert(it != std::end(T##_names)); return it->second; \
} \
\
template <> \
optional<T> Enum<T>::toEnum(const std::string& s) { \
auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \
[&] (const auto& v) { return s == v.second; }); \
return it == std::end(T##_names) ? optional<T>() : it->first; \
}

} // namespace mbgl
2 changes: 2 additions & 0 deletions platform/default/src/mbgl/gl/headless_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class HeadlessRenderableResource final : public gl::RenderableResource {
depthStencil(context.createRenderbuffer<gfx::RenderbufferPixelType::DepthStencil>(size_)),
framebuffer(context.createFramebuffer(color, depthStencil)) {}

~HeadlessRenderableResource() noexcept override = default;

void bind() override {
context.bindFramebuffer = framebuffer.framebuffer;
context.scissorTest = false;
Expand Down
8 changes: 6 additions & 2 deletions platform/default/src/mbgl/storage/sqlite3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/util/optional.hpp>

#define MBGL_CONSTRUCTOR(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)

namespace mapbox {
namespace sqlite {

Expand Down Expand Up @@ -102,8 +107,7 @@ void logSqlMessage(void *, const int err, const char *msg) {
}
#endif

__attribute__((constructor))
static void initalize() {
MBGL_CONSTRUCTOR(initialize) {
if (sqlite3_libversion_number() / 1000000 != SQLITE_VERSION_NUMBER / 1000000) {
char message[96];
snprintf(message, 96,
Expand Down
8 changes: 7 additions & 1 deletion platform/default/src/mbgl/util/compression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
#include <cstring>
#include <stdexcept>

#if defined(__GNUC__)
#define MBGL_UNUSED __attribute__((unused))
#else
#define MBGL_UNUSED
#endif

// Check zlib library version.
const static bool zlibVersionCheck __attribute__((unused)) = []() {
const static bool zlibVersionCheck MBGL_UNUSED = []() {
const char *const version = zlibVersion();
if (version[0] != ZLIB_VERSION[0]) {
char message[96];
Expand Down
4 changes: 2 additions & 2 deletions platform/qt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ The Windows build will assume you have installed and on the default path:

- Microsoft Visual Studio 2015
- [CMake 3.10.1+](https://cmake.org/download/)
- [LLVM 5.0.0+](https://releases.llvm.org/download.html)
- [Qt 5+](https://www.qt.io/download) with "msvc2015" support.
- [LLVM 5.0.0+](https://releases.llvm.org/download.html) (optional)
- [Qt 5.4+](https://www.qt.io/download) with "msvc2015" (or later) support.

At runtime, you will also need installed:

Expand Down
11 changes: 8 additions & 3 deletions platform/qt/app/mapwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,16 +448,21 @@ void MapWindow::mouseMoveEvent(QMouseEvent *ev)

void MapWindow::wheelEvent(QWheelEvent *ev)
{
if (ev->orientation() == Qt::Horizontal) {
if (ev->angleDelta().y() == 0) {
return;
}

float factor = ev->delta() / 1200.;
if (ev->delta() < 0) {
float factor = ev->angleDelta().y() / 1200.;
if (ev->angleDelta().y() < 0) {
factor = factor > -1 ? factor : 1 / factor;
}

#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
m_map->scaleBy(1 + factor, ev->position());
#else
m_map->scaleBy(1 + factor, ev->pos());
#endif

ev->accept();
}

Expand Down
72 changes: 50 additions & 22 deletions platform/qt/qt.cmake
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# Note: Using Sqlite instead of QSqlDatabase for better compatibility.

find_package(Qt5Gui REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Widgets REQUIRED)

if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
find_package(Qt${QT_VERSION_MAJOR}
COMPONENTS Gui
Network
OpenGL
OpenGLWidgets
Widgets
REQUIRED)

if(MSVC)
add_definitions("/DQT_COMPILING_QIMAGE_COMPAT_CPP")
add_definitions("/D_USE_MATH_DEFINES")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_definitions("-DQT_COMPILING_QIMAGE_COMPAT_CPP")
add_definitions("-D_USE_MATH_DEFINES")
add_definitions("-Wno-deprecated-declarations")
Expand Down Expand Up @@ -88,10 +94,10 @@ target_link_libraries(
PRIVATE
$<$<NOT:$<PLATFORM_ID:Windows>>:z>
$<$<NOT:$<PLATFORM_ID:Windows>>:mbgl-vendor-icu>
Qt5::Core
Qt5::Gui
Qt5::Network
Qt5::OpenGL
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::OpenGL
mbgl-vendor-nunicode
mbgl-vendor-sqlite
)
Expand Down Expand Up @@ -135,8 +141,8 @@ target_compile_definitions(
target_link_libraries(
qmapboxgl
PRIVATE
Qt5::Core
Qt5::Gui
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
mbgl-compiler-options
mbgl-core
)
Expand All @@ -155,8 +161,9 @@ set_property(TARGET mbgl-qt PROPERTY CXX_STANDARD 98)
target_link_libraries(
mbgl-qt
PRIVATE
Qt5::Widgets
Qt5::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
mbgl-compiler-options
qmapboxgl
)
Expand All @@ -176,20 +183,41 @@ target_compile_definitions(
PRIVATE WORK_DIRECTORY=${PROJECT_SOURCE_DIR}
)

target_link_libraries(
mbgl-test-runner
PRIVATE
Qt5::Gui
Qt5::OpenGL
mbgl-compiler-options
pthread
)
if (MSVC)
target_link_libraries(
mbgl-test-runner
PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::OpenGL
mbgl-compiler-options
)
else()
target_link_libraries(
mbgl-test-runner
PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::OpenGL
mbgl-compiler-options
pthread
)
endif()

if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
target_link_libraries(
mbgl-test-runner
PRIVATE -Wl,-force_load mbgl-test
)
elseif(MSVC)
target_link_options(
mbgl-test-runner
PRIVATE /WHOLEARCHIVE:../../lib/mbgl-test.lib
)
target_link_libraries(
mbgl-test-runner
PRIVATE mbgl-test
)
else()
target_link_libraries(
mbgl-test-runner
Expand Down
10 changes: 6 additions & 4 deletions platform/qt/src/bidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ std::vector<StyledText> BiDi::processStyledText(const StyledText& input, std::se
std::vector<StyledText> transformedLines;
std::size_t start = 0;
for (std::size_t lineBreakPoint : lineBreakPoints) {
transformedLines.emplace_back(
input.first.substr(start, lineBreakPoint - start),
std::vector<uint8_t>(input.second.begin() + start, input.second.begin() + lineBreakPoint));
start = lineBreakPoint;
if (lineBreakPoint <= input.second.size()) {
transformedLines.emplace_back(
input.first.substr(start, lineBreakPoint - start),
std::vector<uint8_t>(input.second.begin() + start, input.second.begin() + lineBreakPoint));
start = lineBreakPoint;
}
}

return transformedLines;
Expand Down
15 changes: 11 additions & 4 deletions platform/qt/src/headless_backend_qt.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include <mbgl/gl/headless_backend.hpp>

#include <QGLWidget>
#include <QOffscreenSurface>
#include <QOpenGLContext>

#include <cassert>
Expand All @@ -10,6 +10,12 @@ namespace gl {

class QtBackendImpl final : public HeadlessBackend::Impl {
public:
QtBackendImpl() {
// QtBackendImpl must be created in the main/GUI thread on platforms
// that have a QWindow-based QOffscreenSurface.
surface.create();
context.create();
}
~QtBackendImpl() = default;

gl::ProcAddress getExtensionFunctionPointer(const char* name) {
Expand All @@ -18,15 +24,16 @@ class QtBackendImpl final : public HeadlessBackend::Impl {
}

void activateContext() {
widget.makeCurrent();
context.makeCurrent(&surface);
}

void deactivateContext() {
widget.doneCurrent();
context.doneCurrent();
}

private:
QGLWidget widget;
QOpenGLContext context;
QOffscreenSurface surface;
};

void HeadlessBackend::createImpl() {
Expand Down
6 changes: 6 additions & 0 deletions platform/qt/src/http_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ void HTTPFileSource::Impl::request(HTTPRequest* req)
}

QNetworkRequest networkRequest = req->networkRequest();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Not needed in Qt6 due to default redirect policy
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
#endif

data.first = m_manager->get(networkRequest);
connect(data.first, SIGNAL(finished()), this, SLOT(onReplyFinished()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(data.first, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onReplyFinished()));
#else
connect(data.first, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyFinished()));
#endif
}

void HTTPFileSource::Impl::cancel(HTTPRequest* req)
Expand Down
10 changes: 10 additions & 0 deletions platform/qt/src/local_glyph_rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ Glyph LocalGlyphRasterizer::rasterizeGlyph(const FontStack&, GlyphID glyphID) {
return glyph;
}

#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
glyph.metrics.width = impl->metrics->horizontalAdvance(glyphID);
#else
glyph.metrics.width = impl->metrics->width(glyphID);
#endif

glyph.metrics.height = impl->metrics->height();
glyph.metrics.left = 3;
glyph.metrics.top = -8;
Expand All @@ -68,8 +73,13 @@ Glyph LocalGlyphRasterizer::rasterizeGlyph(const FontStack&, GlyphID glyphID) {
// Render at constant baseline, to align with glyphs that are rendered by node-fontnik.
painter.drawText(QPointF(0, 20), QString(QChar(glyphID)));

#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto img = std::make_unique<uint8_t[]>(image.sizeInBytes());
memcpy(img.get(), image.constBits(), image.sizeInBytes());
#else
auto img = std::make_unique<uint8_t[]>(image.byteCount());
memcpy(img.get(), image.constBits(), image.byteCount());
#endif

glyph.bitmap = AlphaImage { size, std::move(img) };

Expand Down
5 changes: 5 additions & 0 deletions platform/qt/src/qmapboxgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,13 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
.rgbSwapped()
.convertToFormat(QImage::Format_ARGB32_Premultiplied);

#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto img = std::make_unique<uint8_t[]>(swapped.sizeInBytes());
memcpy(img.get(), swapped.constBits(), swapped.sizeInBytes());
#else
auto img = std::make_unique<uint8_t[]>(swapped.byteCount());
memcpy(img.get(), swapped.constBits(), swapped.byteCount());
#endif

return std::make_unique<mbgl::style::Image>(
id.toStdString(),
Expand Down
5 changes: 5 additions & 0 deletions platform/qt/src/qt_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ PremultipliedImage decodeImage(const std::string& string) {
throw std::runtime_error("Unsupported image type");
}

#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto img = std::make_unique<uint8_t[]>(image.sizeInBytes());
memcpy(img.get(), image.constBits(), image.sizeInBytes());
#else
auto img = std::make_unique<uint8_t[]>(image.byteCount());
memcpy(img.get(), image.constBits(), image.byteCount());
#endif

return { { static_cast<uint32_t>(image.width()), static_cast<uint32_t>(image.height()) },
std::move(img) };
Expand Down
Loading