diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index d0121e40..65dd81b3 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -28,6 +28,7 @@ find_package(QT NAMES Qt6 OpenGL OpenGLWidgets Positioning + Svg Widgets REQUIRED) find_package(Qt${QT_VERSION_MAJOR} @@ -38,6 +39,7 @@ find_package(Qt${QT_VERSION_MAJOR} OpenGL OpenGLWidgets Positioning + Svg Widgets REQUIRED) @@ -552,6 +554,7 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGLWidgets Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Positioning + Qt${QT_VERSION_MAJOR}::Svg Boost::json Boost::timer QMapLibre::Core diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp index fbb4f187..554cecbe 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #if defined(_MSC_VER) @@ -49,6 +52,11 @@ public: static std::shared_ptr LoadImage(const std::string& imagePath); + static std::shared_ptr + ReadPngFile(const QString& imagePath); + static std::shared_ptr + ReadSvgFile(const QString& imagePath); + std::vector> registeredTextures_ {}; std::shared_mutex registeredTextureMutex_ {}; @@ -376,34 +384,23 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) { logger_->debug("Loading image: {}", imagePath); - std::shared_ptr image = - std::make_shared(); + std::shared_ptr image = nullptr; - QUrl url = QUrl::fromUserInput(QString::fromStdString(imagePath)); + QString qImagePath = QString::fromStdString(imagePath); + + QUrl url = QUrl::fromUserInput(qImagePath); if (url.isLocalFile()) { - QFile imageFile(imagePath.c_str()); + QString suffix = QFileInfo(qImagePath).suffix().toLower(); - imageFile.open(QIODevice::ReadOnly); - - if (!imageFile.isOpen()) + if (suffix == "svg") { - logger_->error("Could not open image: {}", imagePath); - return nullptr; + image = ReadSvgFile(qImagePath); } - - boost::iostreams::stream dataStream(imageFile); - - try + else { - boost::gil::read_and_convert_image( - dataStream, *image, boost::gil::png_tag()); - } - catch (const std::exception& ex) - { - logger_->error("Error reading image: {}", ex.what()); - return nullptr; + image = ReadPngFile(qImagePath); } } else @@ -442,6 +439,7 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) width * desiredChannels); // Copy the view to the destination image + image = std::make_shared(); *image = boost::gil::rgba8_image_t(stbView); auto& view = boost::gil::view(*image); @@ -477,6 +475,69 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) return image; } +std::shared_ptr +TextureAtlas::Impl::ReadPngFile(const QString& imagePath) +{ + QFile imageFile(imagePath); + + imageFile.open(QIODevice::ReadOnly); + + if (!imageFile.isOpen()) + { + logger_->error("Could not open image: {}", imagePath.toStdString()); + return nullptr; + } + + boost::iostreams::stream dataStream(imageFile); + std::shared_ptr image = + std::make_shared(); + + try + { + boost::gil::read_and_convert_image( + dataStream, *image, boost::gil::png_tag()); + } + catch (const std::exception& ex) + { + logger_->error("Error reading image: {}", ex.what()); + return nullptr; + } + + return image; +} + +std::shared_ptr +TextureAtlas::Impl::ReadSvgFile(const QString& imagePath) +{ + QSvgRenderer renderer {imagePath}; + QPixmap pixmap {renderer.defaultSize()}; + pixmap.fill(Qt::GlobalColor::transparent); + + QPainter painter {&pixmap}; + renderer.render(&painter, pixmap.rect()); + + QImage qImage = pixmap.toImage(); + + std::shared_ptr image = nullptr; + + if (qImage.width() > 0 && qImage.height() > 0) + { + // Convert to ARGB32 format if not already (equivalent to bgra8_pixel_t) + qImage.convertTo(QImage::Format_ARGB32); + + // Create a view pointing to the underlying QImage pixel data + auto view = boost::gil::interleaved_view( + qImage.width(), + qImage.height(), + reinterpret_cast(qImage.constBits()), + qImage.width() * 4); + + image = std::make_shared(view); + } + + return image; +} + TextureAtlas& TextureAtlas::Instance() { static TextureAtlas instance_ {};