Git Product home page Git Product logo

qnanopainter's Introduction

QNanoPainter

QNanoPainter is an OpenGL accelerated C++ vector drawing library for Qt, offering optimal performance, productivity and rendering quality all-in-one. QNanoPainter API is a mixture of QPainter and HTML5 canvas APIs. In other words, it's very close to HTML5 canvas but transformed to object oriented C++ with separate classes.

QNanoPainter can be used together with Qt5 UIs in different ways:

  • Use QNanoQuickItem and QNanoQuickItemPainter when implementing custom C++ Qt QQuickItems. This is comparable to QQuickPaintedItem, but instead of QPainter offers own QNanoPainter API for drawing.
  • Use QNanoWidget when implementing custom QWidget. This is based on QOpenGLWidget.
  • Use QNanoWindow when implementing single-view UI, optimal for embedded usage. This is based on QOpenGLWindow.

QNanoPainter uses excellent NanoVG as its rendering backend.

Screenshots

Features

Here is a non exhaustive list of QNanoPainter features:

  • Vector drawing: Path-based drawing of rectangles, circles, lines etc. filled and/or stroked. Brush can be color, gradient or image pattern. Different cap and join options for stoked lines.
  • Images: Transformed images or rectangular areas of images. Mipmapping for smoother rendering of scaled images.
  • Text: Contains set of default fonts and supports loading custom truetype fonts. Text aligning and wrapping. Letter-spacing and blur for shadow/glow effect.
  • Antialiasing: Adjustable antialiasing amount for vector drawing.
  • Pixel aligning: Drawing and texts can be either freely positioned (smooth animations) or aligned to pixels (sharp rendering).
  • Extra: Supports high-DPI retina resolutions, global alpha, transforms, painter states etc.

Usage

Taking QNanoPainter into use in your Qt application is simple:

  • Copy 'libqnanopainter' directory into your project. Sources are included directly instead of building separate static/dynamic library which makes usage simple and allows easier customization of QNanoPainter itself.
  • In your project .pro file, include QNanoPainter with something like:
include(src/libqnanopainter/include.pri)

For custom QQuickItem

  • Implement your QNanoQuickItem and QNanoQuickItemPainter based classes (see more about these below or from available examples).
  • Export your item into QML in main.cpp with something like:
qmlRegisterType<MyQNanoItem>("MyQNanoItem", 1, 0, "MyQNanoItem");
  • Use your item in QML:
import QtQuick 2.4
import MyQNanoItem 1.0

Item {
	...
	MyQNanoItem {
		anchors.fill: parent
	}
}

To create own QNanoPainter item you should implement 2 classes:

  • QNanoQuickItem: This will be the visual QQuickItem providing API towards QML side. Your painter will be created and attached to item in createItemPainter() method.
  • QNanoQuickItemPainter: This will handle the drawing using QNanoPainter API in the paint() method. Data with the item will be transferred in synchronize() method.

The main reason for two classes is that these will run in separate threads for optimal performance. And because of this, all communication between these two need to happen in synchronize() method.

Here is a complete HelloWorld example item:

#include "qnanoquickitem.h"
#include "qnanoquickitempainter.h"

// HelloItemPainter contains the painting code
class HelloItemPainter : public QNanoQuickItemPainter
{
    Q_OBJECT

public:
    HelloItemPainter()
    {
    }

    void paint(QNanoPainter *p)
    {
        // Paint the background circle
        p->beginPath();
        p->circle(width()*0.5, height()*0.5, width()*0.46);
        QNanoRadialGradient gradient1(width()*0.5, height()*0.4, width()*0.6, width()*0.2);
        gradient1.setStartColor("#808080");
        gradient1.setEndColor("#404040");
        p->setFillStyle(gradient1);
        p->fill();
        p->setStrokeStyle("#202020");
        p->setLineWidth(width()*0.02);
        p->stroke();
        // Hello text
        p->setTextAlign(QNanoPainter::ALIGN_CENTER);
        p->setTextBaseline(QNanoPainter::BASELINE_MIDDLE);
        QNanoFont font1(QNanoFont::DEFAULT_FONT_BOLD_ITALIC);
        font1.setPixelSize(width()*0.08);
        p->setFont(font1);
        p->setFillStyle("#B0D040");
        p->fillText("HELLO", width()*0.5, height()*0.4);
        // QNanoPainter text
        QNanoFont font2(QNanoFont::DEFAULT_FONT_THIN);
        font2.setPixelSize(width()*0.18);
        p->setFont(font2);
        p->fillText("QNanoPainter", width()*0.5, height()*0.5);
    }
};

// HelloItem provides the API towards QML
class HelloItem : public QNanoQuickItem
{
    Q_OBJECT

public:
    HelloItem(QQuickItem *parent = 0)
        :  QNanoQuickItem(parent)
    {
    }

    // Reimplement
    QNanoQuickItemPainter *createItemPainter() const
    {
        // Create painter for this item
        return new HelloItemPainter();
    }
};

For custom QWidget or QWindow

Implement your own QNanoWidget or QNanoWindow subclass depending on your needs. APIs of these are very similar, basically you just override paint() method like this:

#include "qnanowindow.h"
#include "qnanopainter.h"

class HelloWindow : public QNanoWindow
{
public:
    HelloWindow()
    {
        setFillColor("#ffffff");
    }

    void paint(QNanoPainter *p)
    {
        // Paint using QNanoPainter here
        ...
    }
};

Example how to render QImage

QNanoPainter can render QImage. The principle is that on the first render pass the QImage is loaded and put into cache and on the second pass it will be used from the cache.

QImage is automatically converted to the correct pixel format (Format_RGBA8888_Premultiplied).

Here's how to do it in paint function:

    QImage loadImage(const QString &fileName)
    {
        // Load and return QImage
        return QImage();
    }

    void paint(QNanoPainter *painter)
    {
        QString imageFileName; // Path to your image file

        QNanoImage nanoImage = QNanoImage::fromCache(painter, imageFileName);
        QSize imageSize(nanoImage.width(), nanoImage.height());
        if (imageSize.isEmpty()) {
            QImage image(loadImage(imageFileName));
            if (image.isNull())
                return;

            nanoImage = QNanoImage(image, imageFileName);
            imageSize = image.size();
        }

        // Render QNanoImage using painter
    }

API Reference

Sources contain API documentation written with QDoc. To generate the documentation:

> cd doc
> [Qt bin path]/qdoc qnanopainter.qdocconf 

Documentation is work-in-progress, patches welcome =)

License

The library is licensed under zlib license.

Links

qnanopainter's People

Contributors

bacarozzo avatar cinderblocks avatar gunrot avatar hartcw avatar jarkkokoivikko-code-q avatar jcelerier avatar kgron avatar mariuszmaximus avatar nielsmayer avatar quitcoding avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qnanopainter's Issues

Linear filtering when scaling QNanoImages from fbos

I am trying to use QNanoImage to perform some zooming operations on a QOpenGLFramebufferObject. I can see that when I load an image from a file and scale the image (using painter->scale), linear filtering is used by default and the image is scaled "smoothly" (similar to the QML standard smooth: true). Now when I try to do the same thing using an fbo, it seems that nearest filtering is always used: the image appears pixelated. The code I am using is the following:

            QNanoImage cacheImage = QNanoImage::fromFrameBuffer(m_cacheBuffer.get(),
                                                                QNanoImage::FLIPY |
                                                                QNanoImage::GENERATE_MIPMAPS);
            painter->scale(m_contentScale);
            painter->drawImage(cacheImage,0,0);

So I decided to blit the fbo directly using:

            QOpenGLFramebufferObject::blitFramebuffer(fbo,QRect(0,0,1000,1000),
                                                      m_cacheBuffer.get(), QRect(0,0,width()/m_contentScale, height()/m_contentScale),
                                                      GL_COLOR_BUFFER_BIT,
                                                      GL_LINEAR);

which actually uses linear filtering and the image appears "smoothly" scaled (it works only if I explicity set GL_COLOR_BUFFER_BIT as the GLbitfield). I don't have too much experience with OpenGL, so I am not sure why would that be the case. Could this be due to format that my fbo is created with?

Can no longer compile on Linux Desktop

After updating recently, I could no longer compile the latest sources for Linux Desktop (Ubuntu 14.04LTS , Qt 5.6 beta #303). Compilation and running on Android still works.

This may have to do with 37cf1c2 from 3ff178c

"Merge pull request #1 from gunrot/master
windows build using angle (glesv2)
Also image&font cache changes."

It appears changes for building on windows weren't propagated or tested on the Linux desktop build??

The Linux desktop version can be built by adding the following lines to the change for windows in qnanopainter/libqnanopainter/include.pri:11

win32  {
    QT_CONFIG += opengles2 angle
}
+unix {
+    DEFINES += QT_OPENGL_ES_2
+}

Note that the above change for Linux desktop is the minimum change I could do to correct the compilation error. I am not sure it is "correct."

The "merge pull request #1" suggests the change to libqnanopainter/include.pro was to "use correct way to specify opengles2". For Linux/Unix, is there a "QT += " module which will correctly set the defines for opengles2? My change reverts to the removed code from the win32 include.pri, which is what gave me the hint to try "DEFINES += QT_OPENGL_ES_2" for the unix build.

 win32  {
-    LIBS += libglesv2.lib
-    DEFINES += QT_OPENGL_ES_2
+    QT_CONFIG += opengles2 angle
 }

NBL The following is the error output seen compiling on Linux desktop without the change made to qnanopainter/libqnanopainter/include.pri:

g++ -c -pipe -O2 -std=gnu++0x -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG_OUTPUT -DQT_NO_INFO_OUTPUT -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I../../../qnanopainter/examples/qnanopainter_vs_qpainter_demo -I/home/npm/android/src/shield/build-qnanopainter-Desktop_Qt_5_6_0_GCC_x86_64bit_in_usr_bin-Release/examples/qnanopainter_vs_qpainter_demo -I../../../qnanopainter/libqnanopainter -I/opt/Qt5.6.0-beta/5.6/gcc_64/include -I/opt/Qt5.6.0-beta/5.6/gcc_64/include/QtQuick -I/opt/Qt5.6.0-beta/5.6/gcc_64/include/QtGui -I/opt/Qt5.6.0-beta/5.6/gcc_64/include/QtQml -I/opt/Qt5.6.0-beta/5.6/gcc_64/include/QtNetwork -I/opt/Qt5.6.0-beta/5.6/gcc_64/include/QtCore -I/home/npm/android/src/shield/build-qnanopainter-Desktop_Qt_5_6_0_GCC_x86_64bit_in_usr_bin-Release/examples/qnanopainter_vs_qpainter_demo -I/opt/Qt5.6.0-beta/5.6/gcc_64/mkspecs/linux-g++ -o qnanopainter.o ../../../qnanopainter/libqnanopainter/qnanopainter.cpp
In file included from ../../../qnanopainter/libqnanopainter/qnanopainter.cpp:38:0:
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h: In function 'int glnvg__renderCreateTexture(void*, int, int, int, int, const unsigned char*)':
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:754:16: error: 'GL_UNPACK_ROW_LENGTH' was not declared in this scope
  glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:755:16: error: 'GL_UNPACK_SKIP_PIXELS' was not declared in this scope
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:756:16: error: 'GL_UNPACK_SKIP_ROWS' was not declared in this scope
  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:762:34: error: 'GL_GENERATE_MIPMAP' was not declared in this scope
   glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
                                  ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:774:34: error: 'GL_RED' was not declared in this scope
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
                                  ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h: In function 'int glnvg__renderUpdateTexture(void*, int, int, int, int, int, const unsigned char*)':
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:832:16: error: 'GL_UNPACK_ROW_LENGTH' was not declared in this scope
  glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:833:16: error: 'GL_UNPACK_SKIP_PIXELS' was not declared in this scope
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:834:16: error: 'GL_UNPACK_SKIP_ROWS' was not declared in this scope
  glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
                ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl.h:851:47: error: 'GL_RED' was not declared in this scope
   glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data);
                                               ^
make[1]: Leaving directory `/home/npm/android/src/shield/build-qnanopainter-Desktop_Qt_5_6_0_GCC_x86_64bit_in_usr_bin-Release/examples/qnanopainter_vs_qpainter_demo'
make[1]: *** [qnanopainter.o] Error 1
make: *** [sub-examples-qnanopainter_vs_qpainter_demo-make_first] Error 2
14:47:54: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project qnanopainter (kit: Desktop Qt 5.6.0 GCC (x86 64bit in /usr/bin))
When executing step "Make"

include qmath.h instead of math.h

When building against qtbase/dev with MSVC I found the following change was needed to get M_PI:

diff --git a/examples/qnanopainter_vs_qpainter_demo/src/demoqpitem.cpp b/examples/qnanopainter_vs_qpainter_demo/src/demoqpitem.cpp
index 96c9b8e..33176c4 100644
--- a/examples/qnanopainter_vs_qpainter_demo/src/demoqpitem.cpp
+++ b/examples/qnanopainter_vs_qpainter_demo/src/demoqpitem.cpp
@@ -3,7 +3,7 @@
#include
#include
#include
-#include <math.h>
+#include <qmath.h>

DemoQPItem::DemoQPItem(QQuickItem *parent)
: QQuickPaintedItem(parent)

garbled display for 'helloitem' example on ChromeOS (aka Android 7.1 on x86) Pixelbook

For both Qt5.9.5 and 5.10.1 Android86 builds on Pixelbook running ChromeOS 65, when displayed fullscreen, damage can be seen in display.
screenshot 2018-04-29 at 12 44 01 pm

Displayed normal size (1098x618) damage is not seen.
screenshot 2018-04-29 at 12 44 48 pm

In both cases the app needs resizing or narrowing so that the bottom of the circle doesn't appear off-screen. However, at least on this stock/default/normal version of ChromeOS on x86 Pixelbook I am unable to free-resize Qt apps between their default size and fullscreen, unlike some android N apps.

The fact that the circle is offscreen is a separate bug. This bug is about the visible damage seen when the 'helloimage' example is displayed fullscreen.

qnanopainter worked with "Ubuntu SDK" based on Qt 5.2.1, now doesn't compile

With the application of a trivial QML patch, QNanoPainter used to compile and work with "Ubuntu SDK" ( https://packages.ubuntu.com/search?keywords=ubuntu-sdk-libs ) which is a convenient way to get Qt5 and a properly working QtMultimedia on Ubuntu (unlike latest Qt 5.6/5.9/5.10 releases).

With latest changes to qnanopainter (TBD -- I'm trying to identify which changes did this compared to my locally working sourcecode).

First error:

qnanopainter/examples/qnanopainter_vs_qpainter_demo/src/demoqnanoitempainter.cpp
g++ -c -m64 -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT -fPIE -DQNANO_QT_GL_INCLUDE -DQNANO_ENABLE_GLES3 -DQT_NO_DEBUG_OUTPUT -DQT_NO_INFO_OUTPUT -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -I../../../copy-of-qnanopainter/examples/qnanopainter_vs_qpainter_demo -I../../../copy-of-qnanopainter/libqnanopainter -I/usr/include/qt5 -I/usr/include/qt5/QtQuick -I/usr/include/qt5/QtQml -I/usr/include/qt5/QtNetwork -I/usr/include/qt5/QtGui -I/usr/include/qt5/QtCore -I. -I. -o qnanopainter.o ../../../copy-of-qnanopainter/libqnanopainter/qnanopainter.cpp
../../../copy-of-qnanopainter/libqnanopainter/qnanopainter.cpp: In constructor β€˜QNanoPainter::QNanoPainter()’:
../../../copy-of-qnanopainter/libqnanopainter/qnanopainter.cpp:145:20: error: β€˜openGLModuleType’ is not a member of β€˜QOpenGLContext’
     bool isGLES = (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
                    ^
../../../copy-of-qnanopainter/libqnanopainter/qnanopainter.cpp:145:58: error: β€˜LibGLES’ is not a member of β€˜QOpenGLContext’
     bool isGLES = (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
                                                          ^

Another:

g++ -c -m64 -pipe -O2 -std=c++0x -Wall -W -D_REENTRANT -fPIE -DQNANO_QT_GL_INCLUDE -DQNANO_ENABLE_GLES3 -DQT_NO_DEBUG_OUTPUT -DQT_NO_INFO_OUTPUT -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -I../../../copy-of-qnanopainter/examples/qnanopainter_vs_qpainter_demo -I../../../copy-of-qnanopainter/libqnanopainter -I/usr/include/qt5 -I/usr/include/qt5/QtQuick -I/usr/include/qt5/QtQml -I/usr/include/qt5/QtNetwork -I/usr/include/qt5/QtGui -I/usr/include/qt5/QtCore -I. -I. -o qnanowindow.o ../../../copy-of-qnanopainter/libqnanopainter/qnanowindow.cpp
In file included from ../../../copy-of-qnanopainter/libqnanopainter/qnanowindow.cpp:22:0:
../../../copy-of-qnanopainter/libqnanopainter/qnanowindow.h:25:25: fatal error: QOpenGLWindow: No such file or directory
 #include <QOpenGLWindow>
                         ^

Just for reference, when running with Ubuntu SDK, (and envar QSG_INFO set to emit debug info), the output looks like:

Starting /home/npm/src/build-qnanopainter-Ubuntu_SDK_5_2_1_GCC_x86_64bit_in_usr_bin-Release/examples/gallery/gallery...
QSG: threaded render loop 
QSG: texture atlas dimensions: 512 x 1024 
GL_VENDOR:      X.Org 
GL_RENDERER:    Gallium 0.4 on AMD CAPE VERDE (DRM 2.48.0, LLVM 3.6.0) 
GL_VERSION:     3.0 Mesa 11.0.4 
GL_EXTENSIONS:
    GL_ARB_multisample

Here is the trivial QML patch to enable gallery and qnanopainter-vs examples to work with Ubuntu SDK. It is trivial in that all it does is roll back Qt versions of various QML imports to whatever was available with Qt 5.2.1.

qnanopainter-make-qml-compatible-with-ubuntu-sdk.patch.gz

qnanopainter screen location float --> "comparing floating point with == or != is unsafe."

As corollary to #31, since qnanopainter uses float to represent screen locations, what is a correct and resolution independent way of comparing screen locations and points without incurring the "comparing floating point with == or != is unsafe." warning?

For example, https://stackoverflow.com/a/10334868 suggests the "epsilon" for an equality check should depend on what would be visually significant on a given display.

Perhaps QNanoPainter needs a primitive similar to CocoaTouch's CGPointEqualToPoint()
as suggested here: https://stackoverflow.com/a/16418684 which ostensibly calculates the "epsilon" for point comparison based on current display properties?

Multiple stops in linear and radial gradient

Is there a plan to support multiple stops in linear and radial gradient? If so when would it be available?
I want to use gradient something like this.

<svg width=300 height=300>
  <defs>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0" stop-color="blue"/>
        <stop offset="0.25" stop-color="red"/>
        <stop offset="0.75" stop-color="green"/>
      </linearGradient>
  </defs>

  <rect x="10" y="10" rx="15" ry="15" width="200" height="200" fill="url(#Gradient2)"/>
</svg>

drawText is not working - building through cmake

Hi,
I am trying to use qnanopainter built using cmakelists.txt. The function call drawText is not able to draw the string on to UI screen. Instead of using the source code directly I am creating a static library and using it. All other calls like Rect, circle, ellipse, line etc are working. Am i missing anything?

Compilation errors with Qt6.0.0

Qt 6.0.0 alpha has been released ( https://www.qt.io/blog/qt-6.0-alpha-released ).

In order to get qnanopainter compilation going at all with Qt6, I first had to modify libqnanopainter/include.pri:

diff --git a/libqnanopainter/include.pri b/libqnanopainter/include.pri
index 079eb6e..6c8ddae 100644
--- a/libqnanopainter/include.pri
+++ b/libqnanopainter/include.pri
@@ -5,6 +5,13 @@ INCLUDEPATH += $$PWD/
 # Use c++11 features
 CONFIG += c++11

+##NPM: for Qt6, need opengl module
+## https://doc-snapshots.qt.io/qt6-dev/qtopengl-index.html
+equals(QT_MAJOR_VERSION, 6) {
+   QT += opengl
+}
+
+
 # Enable this to get drawing debug information
 #DEFINES += QNANO_DEBUG

With this change in place, I was able to get compilation going, but with numerous errors -- see attached file.
There are lots of deprecation warnings, but I'm not going to concentrate on that here.

Some examples of such errors;

  • error: β€˜geometryChanged’ is not a member of β€˜QQuickItem’

  • error: β€˜class QQuickWindow’ has no member named β€˜resetOpenGLState’; did you mean β€˜setWindowState’?

  • fatal error: QOpenGLWidget: No such file or directory

Others are more trivial:

  • error: β€˜qrand’ was not declared in this scope

wrong usage of QCache for font and images

Either you or I have a misunderstanding in how QCache works.
When reading documentation, i read that it takes ownership and deletes an item any time it wants.
But this way you cannot stay in sync with the font stored in fontstash. you also use new for data which is deleted with free. Also a font in use may not be in the cache, as any other insert can lead to removal and deletion. Next time you use this removed font you will add it again in font stash.
Only q implicit shared objects could be used by doing insert(key,new QImage(myImage)). .
i made a change to fix that by not using the cache at all, but use nvgFindFont to find an existing font.

see commit ea9a287 at github.com/gunrot/qnanopainter ( also in the pull request now by accident, i don't have a proper understanding of this for now it seems)

Similar issues exist with the image caching, but there is no possibility in nanovg to find an image by name. So i would just change the QCache to a QMap to have a name to id mapping.
The current usage of Cache, will lead to images be forgotten in the nag store, as QCache will evict the dataeleemwnt but not remove the image from the store.so the next time the image is added agin in the store as it has been forgotten.

I also do not think the caching should be on item level, but should be globally shared. so items using the same font and images can shared them.
But as i understand it, each item has its itempainter, which holds its own nvg context ( storing fonts and images) and its own painter.

This architecture seems to be not efficient if i want to use about 100 quicknanoitems on the screen. especially if they use the same fonts and or images.

so could the nvg context be shared between quicknanoitems?

Best regards,
Gunnar Roth

Effective way to erase painting?

I'm trying to implement a eraser, clear subregion of the texture.

PageCanvas is child of QNanoQuickItem and render with QQuickFramebufferObject, what i do is binding the texture then glTexSubImage2D. But it crashs. So where is the right place(QNanoQuickItemPainter?) to do this operation, or i'm using the texture in a wrong way.

void PageCanvas::erase(int x, int y)
{
    textureProvider()->texture()->bind();
    const int eraserSize = 16;
    quint32 subImage[eraserSize * eraserSize] = {};
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, eraserSize, eraserSize, GL_RGBA, GL_UNSIGNED_BYTE, subImage);
}

Performance with no QNANO_USE_RENDERNODE

Hi,

We are making an application that is generating dinamically QNanoQuickItem Custom Items, all the items created are sharing the same parent.
The behavoiur is nice but we are getting some "issues" when overloading the number of items created.

We are adding qputenv("QSG_RENDERER_DEBUG", "render"); to check how is the render behaviour and we can see the number of "batches" is incrising each time we create a new QNanoQuickItem. And that is doing our render effect degrade the performance because of that.
As additional point, we have checked the same app but based on QQuickItem Custom Items, and in this case the number of "batches" is not incrised and not degrading the performance behaviour.

Is this the common behaviour and I have to assume it, or is there a way to change this behaviour?

crash when using a gradient brush for stroke

Hi,
seems that

    // Set parent painter for brush
    QNanoBrush* b = const_cast<QNanoBrush*>(&brush);
    if (b) {
        b->setParentPainter(this);
    }

is missing in void QNanoPainter::setStrokeStyle(const QNanoBrush &brush).

Seeing this const_casts here and there , i would consider making setParentPainter const and the member 'parentPainter' mutable.

Problem with strokes and overlapping transparent colors.

When the stroke (pen) color is transparent (e.g. 0xAAE00000) then overlapping regions (e.g. around joints) add up.
The problem can be tested by setting a fixed angle m_animationSine = 10*M_PI/180.0; in "galleryitempainter.cpp".

patch to compile on Raspberry Pi/Raspbian Stretch and extremely variable performance with qnanopainter_vs_qpainter_demo testing

Using https://www.tal.org/tutorials/building-qt-512-raspberry-pi I built latest Qt release on latest Raspbian Stretch distro (aka debian 9)

Unfortunately, when compiling qnanopainter it gives compilation errors:

g++ -c -pipe -march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQNANO_QT_GL_INCLUDE -DQNANO_ENABLE_GLES3 -DQT_NO_DEBUG_OUTPUT -DQT_NO_INFO_OUTPUT -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I../../libqnanopainter -I/opt/Qt5.12/include -I/opt/Qt5.12/include/QtQuick -I/opt/Qt5.12/include/QtGui -I/opt/Qt5.12/include/QtQml -I/opt/Qt5.12/include/QtNetwork -I/opt/Qt5.12/include/QtCore -I. -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -I/opt/Qt5.12/mkspecs/linux-rpi3-g++ -o qnanobackendgl2.o ../../libqnanopainter/private/qnanobackendgl2.cpp In file included from ../../libqnanopainter/private/qnanobackendgl2.cpp:12:0: ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h: In function β€˜int glnvg__renderCreateTexture(void*, int, int, int, int, const unsigned char*)’: ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:742:33: error: β€˜GL_UNPACK_ROW_LENGTH’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); ^~~~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:743:33: error: β€˜GL_UNPACK_SKIP_PIXELS’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); ^~~~~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:744:33: error: β€˜GL_UNPACK_SKIP_ROWS’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); ^~~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:750:51: error: β€˜GL_GENERATE_MIPMAP’ was not declared in this scope QNANO_GLFWRAPPER glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); ^~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h: In function β€˜int glnvg__renderUpdateTexture(void*, int, int, int, int, int, const unsigned char*)’: ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:833:33: error: β€˜GL_UNPACK_ROW_LENGTH’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); ^~~~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:834:33: error: β€˜GL_UNPACK_SKIP_PIXELS’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); ^~~~~~~~~~~~~~~~~~~~~ ../../libqnanopainter/nanovg/nanovg_gl_wrapped.h:835:33: error: β€˜GL_UNPACK_SKIP_ROWS’ was not declared in this scope QNANO_GLFWRAPPER glPixelStorei(GL_UNPACK_SKIP_ROWS, y); ^~~~~~~~~~~~~~~~~~~ Makefile:3703: recipe for target 'qnanobackendgl2.o' failed make[1]: *** [qnanobackendgl2.o] Error 1
Some of the undeclared values are present in include files so it is unclear what is missing to get these defined. I will investigate further but wanted to report this problem in case others are seeing it.

npm@rpi2:/usr/local/src/qnanopainter$ grep -r GL_UNPACK_ROW_LENGTH /usr/include/
/usr/include/epoxy/gl_generated.h:#define GL_UNPACK_ROW_LENGTH                                            0x0CF2
/usr/include/epoxy/gl_generated.h:#define GL_UNPACK_ROW_LENGTH_EXT                                        0x0CF2
/usr/include/GL/gl.h:#define GL_UNPACK_ROW_LENGTH                       0x0CF2
/usr/include/GL/glcorearb.h:#define GL_UNPACK_ROW_LENGTH              0x0CF2

npm@rpi2:/usr/local/src/qnanopainter$ grep -r GL_UNPACK_ROW_LENGTH /opt/Qt5.12/include/
/opt/Qt5.12/include/QtGui/5.12.3/QtGui/private/qopengltexturehelper_p.h:        functions->glGetIntegerv(GL_UNPACK_ROW_LENGTH, &val);
/opt/Qt5.12/include/QtGui/5.12.3/QtGui/private/qopengltexturehelper_p.h:        functions->glPixelStorei(GL_UNPACK_ROW_LENGTH, options.rowLength());
/opt/Qt5.12/include/QtGui/qopengles2ext.h:#define GL_UNPACK_ROW_LENGTH_EXT          0x0CF2

qnanopainter.raspi-fail.txt

QNANO_PROPERTY(double...) -> "comparing floating point with == or != is unsafe."

On upgrading to QtCreator 4.7.1 and Qt5.11.2, I noticed massive numbers of clang-code-model warnings appearing in qnanopainter related source-code.

In particular, when using QNANO_PROPERTY(double,....) one is greeted by warnings that "comparing floating point with == or != is unsafe." In researching this issue, I was greeted by the sound of a can of worms opening: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

In the above macro, the problem code in question is:
void setter(type const &v) { if(v == variable) return; variable = v; emit getter##Changed(); update(); }

What is the "correct" way of eliminating the above warning and any "danger" concerns it may cause? How unsafe is this in practice? I notice the only instances of such code in qnanopainter source are commented out https://github.com/QUItCoding/qnanopainter/blob/master/examples/gallery/qnanopainter_features/src/galleryitem.h and that custom code is used for examples where Animation float values are passed in from QML.

Possible memory leak

I am writing a QQuick 2.0 application based on qnanopainter with QNANO_USE_RENDERNODE activated.
I have a custom QNanoQuickItem that is returning on "createItemPainter" method a custom QNanoQuickItemPainter that basically do this on "paint" method:

painter()->beginPath();
painter()->moveTo(x, y);
painter()->quadTo(x1, y1);
painter()->stroke();

The result is very fine and I am getting a high performance.

Also I am creating several custom QNanoQuickItem (all the creation actions are made in C++) and I can make actions over them separately:

  • move
  • transform
  • delete

The point is I can see that the application is not releasing the memory once I delete my custom QNanoQuickItem.
I am checking the destructors on my clases and everything is ok.
I am using "Visual Leak Detector"(VLD) to try to detect the leak and all is pointing to the application is leaking/accumulating memory on qnanopainter side.
VLD report is telling the memory allocated/reallocated on glnvg__allocFragUniforms/glnvg__allocVerts/glnvg__renderStroke/nvg__allocTempVerts is never released.

So, the behavior I can see is:

  • Inc the use of memory when creating items: That is more than ok
  • The memory is not released when erasing created items

Until now, reading qnanopainter code and tracing it, it looks like the library is accumulating memory for render tasks on QNanoPainter instance.

Is there something I can do to release that memory? I am over loading qnanopainter solution?

Fixed Qt6.0.0-beta compile errors, some runtime deprecation warnings remain, 'gallery'->mouse event boxes issue noticed.

  1. #58 -- a few more compilation errors fixed when compiling with Qt6.0.0-beta ( https://www.qt.io/blog/qt-6.0-beta-released ). As of "beta 2" the pull request allows compiling and running.
  2. When running "gallery" I note a deprecation warning that arises for Qt6
    W libgallery_x86_64.so: qrc:/qnanopainter_features/main.qml:80:13: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
    I decided to leave these errors alone in this pull request because fixing it is not "clean" -- there is no QML "ifdef" so some kind of dynamic loading hack of two different QML files would be needed: one file for Qt>=6.0 and another for Qt5.
  3. For Qt6 with PR #58 applied, when in 'gallery'->'Mouse Events Boxes', a single giant box is drawn rather than the random assortment normally seen. The expected display only occurs after clicking the "Random" button. The above PR does not fix this issue, so I'm documenting it here in hope it can be resolved in the future.

Screenshot 2020-11-04 at 9 04 40 PM

NanoVG link-phase warnings when using g++ "-O3 -flto" optimization flags.

I recompiled the latest QNanoPainter after adding the following optimization tweaks to libqnanopainter/include.pri

## NPM: Turn optimization up to 11 for Release build.
## NPM: Use optimized debugging "-Og enables optimizations that do not interfere with debugging. It should be the optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization while maintaining fast compilation and a good debugging experience."
## https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Optimize-Options.html
QMAKE_CFLAGS_OPTIMIZE_SIZE =  ##note that /opt/Qt5.12.0/5.12.0/android_armv7/mkspecs/common/gcc-base.conf sets this to "-Os" and uses for Android Arm builds (only) automatically. This unsets it and gives full optimized android arm builds.
QMAKE_CFLAGS_RELEASE   = -flto -ffast-math -O3
QMAKE_CFLAGS_DEBUG     = -g -Og
QMAKE_CXXFLAGS_RELEASE = -flto -ffast-math -O3
QMAKE_CXXFLAGS_DEBUG   = -g -Og
QMAKE_LFLAGS_RELEASE   = -flto -O3
QMAKE_LFLAGS_DEBUG     = -g -Og

In linking, the following strange warnings are produced related to NanoVG:

g++ -flto -O3 -Wl,-rpath,/opt/Qt5.12.0/5.12.0/gcc_64/lib -o qnanopainter_vs_qpainter_demo main.o demoqpitem.o demoqnanoitem.o demoqnanoitempainter.o qnanopainter.o qnanocolor.o qnanolineargradient.o qnanoimagepattern.o qnanoimage.o qnanofont.o qnanoradialgradient.o qnanoboxgradient.o qnanowindow.o qnanodebug.o qnanoquickitem.o qnanoquickitempainter.o qnanobackendgl2.o qnanobackendgl3.o nanovg.o qrc_qml_qmlcache.o qrc_libqnanopainterdata.o main_qml.o qml_Button_qml.o qml_FpsItem_qml.o qml_TabView_qml.o qml_SliderSelector_qml.o qml_Switch_qml.o qml_SettingsView_qml.o qml_shapeitem_RulerComponent_qml.o qml_shapeitem_FlowerComponent_qml.o qml_shapeitem_LinesComponent_qml.o qml_shapeitem_DemoShapeItem_qml.o qml_shapeitem_BarsComponent_qml.o qml_shapeitem_IconsComponent_qml.o qml_shapeitem_CirclesComponent_qml.o qmlcache_loader.o moc_demoqpitem.o moc_demoqnanoitem.o moc_qnanowindow.o moc_qnanoquickitem.o   -L/opt/Qt5.12.0/5.12.0/gcc_64/lib -lQt5Quick -lQt5Gui -lQt5Qml -lQt5Network -lQt5Core -lGL -lpthread   
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: warning: type β€˜struct GLNVGcontext’ violates the C++ One Definition Rule [-Wodr]
 struct GLNVGcontext {
        ^
make[1]: Leaving directory '/usr/local/src/build-qnanopainter-Qt5_12_0_Desktop_GCC_C_x86_64bit_in_usr_bin-Release/examples/helloitem'
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: note: a different type is defined in another translation unit
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:245:6: note: the first difference of corresponding definitions is field β€˜fragSize’
  int fragSize;
      ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:240:9: note: a field with different name is defined in another translation unit
  GLuint vertArr;
         ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: warning: type β€˜struct GLNVGcontext’ violates the C++ One Definition Rule [-Wodr]
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: note: a different type is defined in another translation unit
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:245:6: note: the first difference of corresponding definitions is field β€˜fragSize’
  int fragSize;
      ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:240:9: note: a field with different name is defined in another translation unit
  GLuint vertArr;
         ^
make[1]: Leaving directory '/usr/local/src/build-qnanopainter-Qt5_12_0_Desktop_GCC_C_x86_64bit_in_usr_bin-Release/examples/hellowindow'
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: warning: type β€˜struct GLNVGcontext’ violates the C++ One Definition Rule [-Wodr]
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: note: a different type is defined in another translation unit
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:245:6: note: the first difference of corresponding definitions is field β€˜fragSize’
  int fragSize;
      ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:240:9: note: a field with different name is defined in another translation unit
  GLuint vertArr;
         ^
make[1]: Leaving directory '/usr/local/src/build-qnanopainter-Qt5_12_0_Desktop_GCC_C_x86_64bit_in_usr_bin-Release/examples/gallery'
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: warning: type β€˜struct GLNVGcontext’ violates the C++ One Definition Rule [-Wodr]
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: note: a different type is defined in another translation unit
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:245:6: note: the first difference of corresponding definitions is field β€˜fragSize’
  int fragSize;
      ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:240:9: note: a field with different name is defined in another translation unit
  GLuint vertArr;
         ^
make[1]: Leaving directory '/usr/local/src/build-qnanopainter-Qt5_12_0_Desktop_GCC_C_x86_64bit_in_usr_bin-Release/examples/hellowidget'
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: warning: type β€˜struct GLNVGcontext’ violates the C++ One Definition Rule [-Wodr]
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:231:8: note: a different type is defined in another translation unit
 struct GLNVGcontext {
        ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:245:6: note: the first difference of corresponding definitions is field β€˜fragSize’
  int fragSize;
      ^
../../../qnanopainter/libqnanopainter/nanovg/nanovg_gl_wrapped.h:240:9: note: a field with different name is defined in another translation unit
  GLuint vertArr;
         ^

I am using Kubuntu 18.04LTS installed g++: "g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0"

How to update QNanoQuickItemPainter's stroke color or size?

I want to dynamic change the painter color and size, but the m_stroke in paint() stay the same:

    void paint(QNanoPainter *p)
    {
        if (m_lines.empty())
            return;

        p->beginPath();
        for (auto& line : m_lines) {
            for (size_t n = 0; n < line.size(); ++n) {
                if (0 == n) {
                    p->moveTo(line[0]);
                } else {
                    p->lineTo(line[n]);
                }
            }
        }

        p->setMiterLimit(15.0f);
        p->setStrokeStyle(QNanoColor::fromQColor(m_stroke.color));
        p->setLineWidth(m_stroke.size);
        qDebug() << "stroke:" << m_stroke.size << "," << m_stroke.color;
        p->setLineJoin(QNanoPainter::JOIN_ROUND);
        p->setLineCap(QNanoPainter::CAP_ROUND);
        p->stroke();
    }
public slots:
    void onStrokeChanged(const int size, const QColor color)
    {
        qDebug() << "onStrokeChanged:" << size << "," << color;
        m_stroke.size = size;
        m_stroke.color = color;
    }

Incorrect drawing with QNANO_USE_RENDERNODE

Let me start by expressing my gratitude to you for this excellent library. QQuickPaintedItem performs suboptimally, Shape renders poorly (seen in your example too), implementing updatePaintNode is difficult because of OpenGL, so an important niche remains which QNanoPainter fits in perfectly. I congratulate you.
Having said that, I have a problem. It's most probably a mistake of mine but I have so far been unable to find it. I have this painting code:

void RoundProgressPainter::paint(QNanoPainter* painter)
{
    painter->beginPath();
    painter->setStrokeStyle(m_color);
    painter->setLineWidth(m_penWidth);
    painter->setLineCap(QNanoPainter::LineCap::CAP_ROUND);
    painter->arc(width() / 2,
                 height() /  2,
                 (height() - m_penWidth) / 2,
                 0,
                 m_progress * 2 * M_PI / 100.0);
    painter->stroke();
}

Using it without QNANO_USE_RENDERNODE (correctly) gives me this:

qquickframebufferobject

Using it with QNANO_USE_RENDERNODE gives me this:

qrendernode

I have a feeling I am making a simple noob mistake so please help me. If necessary, I can provide the rest of my C++ as well as its usage in QML.

How to set the Z value?

I want to paint path item covering other items in the same scene graph. how to set the z value when painting?

Is it possible to integrate Qwt plot and qnanopainter ?

Hi.

I'm using Qwt lib to render a graph, my app uses qml, but as you know Qwt bases on QWidget, so I used QQuickPaintedItem to paint the output of Qwt to my qml app, inspired are from https://github.com/carlos22/qwtquick2.

But this is a performance issue QTBUG-96205 of using QQuickPaintedItem to render a "QWidget's content".

Even though I enabled the QwtPlotOpenGLCanvas of Qwt but I found that this optimization only works for QWidget applications because QOpenGLWidget does not support the render() function with OpenGL. QwtPlotOpenGLCanvas is working well with a widget application, this is example app of Qwt. https://github.com/opencor/qwt/tree/master/examples/refreshtest.

So qnanopainter can help solving the QQuickPaintedItem's performance issue in this case. can't it ?

Actually I tried below solution, the frequency of calling this paint() or update the graph is 40 ms, but my implementation could not solve the CPU% that takes a lot of memory, I guess it is from creating the images.

void QwtQuickPainter::paint(QNanoPainter *painter)
{
    static int index = 0;
   QwtPlotOpenGLCanvas* plotCanvas = qobject_cast< QwtPlotOpenGLCanvas* >( m_qwtPlot->canvas() );
    QNanoImage nImage(plotCanvas->grab(QRect(0, 0, width(), height())).toImage(), QString::number(index));
    painter->drawImage(nImage, 0, 0, width(), height());
    index++;
}

Thanks for your advice !

ASSERT failure in QNanoPainter::QNanoPainter: "No QOpenGL Context available!",

I keep getting this runtime error. I followed the instructions and included the project using:

include(libqnanopainter/include.pri)

Then I created a simple class like below:

#ifndef NANOITEM_H
#define NANOITEM_H

#include <QQuickItem>
#include <QPolygonF>

#include "qnanoquickitem.h"
#include "qnanoquickitempainter.h"

class NanoItem : public QNanoQuickItem
{
    Q_OBJECT
public:
    NanoItem(QQuickItem* item = nullptr);
    QNanoQuickItemPainter *createItemPainter() const;

private:
    QNanoQuickItemPainter* m_painter;
    QPolygonF m_points;

    friend class MyPainter;
    // QQuickItem interface
protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
};



#endif // NANOITEM_H

But when I run the program I keep getting:

ASSERT failure in QNanoPainter::QNanoPainter: "No QOpenGL Context available!", file ../nanopaintertest/libqnanopainter/qnanopainter.cpp, line 142

I am able to run the examples just fine, but I am not sure what is causing this error.

Patch qnanopainter.cpp to fix warning from Clang-Tidy/Clazy: "[bugprone-incorrect-roundings]"

As I mentioned in #32 (comment)
I ran Qt5.12.1's qtcreator "Analyze->Clang-Tidy and Clazy..." and it complained about the rounding in code from

if (a) *a = (static_cast<int>(*a * m_devicePixelRatio + 0.5f)) / m_devicePixelRatio;
through
if (b) *b = (static_cast<int>(*b * m_devicePixelRatio + 0.5f)) / m_devicePixelRatio;
:

: warning: casting (double + 0.5) to integer leads to incorrect rounding; consider using lround (#include <cmath>) instead [bugprone-incorrect-roundings]

Enclosed is a patch to fix the warning:

qnanopainter.cpp.patch.txt

Unlike the "Clang-Tidy and Clazy..." suggestion "<cmath.h>", I used "<qmath.h>" because #20 indicates cmath.h causes error on MSVC.

gallery crash on exit windows qt59

Hello thanks for the superb lib. I noticed that there is something crash as following backtrace on windows at exit

1

2

To reproduce

  1. Im using qt59 opengl dynamic
  2. cd where to example gallery source qmake && jom && debug\gallery.exe
  3. Close it

Performance questions

In the small qnanopainter vs qpainter benchmark, I have roughly 60 fps for QPainter and 40 - 45 fps for QNanoPainter.

What could be the cause of inferior performance ?

Linking failure with <= Qt 5.12.3 on Windows

Win compilation on 5.9.x goes smooth and fine. Compiling the library on Qt 5.12.x Windows (tested both 5.12.1 and 5.12.3) results instead in a failure with the following linking issues:

libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x12b): undefined reference to `_imp__glDeleteTextures@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1b4): undefined reference to `glDeleteShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d5): undefined reference to `glDeleteBuffers@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1e5): undefined reference to `glDeleteShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f5): undefined reference to `glDeleteProgram@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x988): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x9a0): undefined reference to `_imp__glPixelStorei@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x9fc): undefined reference to `_imp__glTexSubImage2D@36'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0xa43): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1361): undefined reference to `_imp__glDeleteTextures@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1388): undefined reference to `_imp__glGetError@0'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1407): undefined reference to `_imp__glGenTextures@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x143a): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1442): undefined reference to `_imp__glPixelStorei@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x14ae): undefined reference to `_imp__glTexImage2D@36'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x14d7): undefined reference to `_imp__glTexParameteri@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1638): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x16b9): undefined reference to `glGenerateMipmap@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x16fa): undefined reference to `_imp__glTexImage2D@36'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x171a): undefined reference to `_imp__glTexParameteri@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x17e0): undefined reference to `glUniform4fv@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1828): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x185f): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x18bb): undefined reference to `glGetProgramInfoLog@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x192e): undefined reference to `glGetShaderInfoLog@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x19c9): undefined reference to `glCreateProgram@0'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x19d7): undefined reference to `glCreateShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x19e8): undefined reference to `glCreateShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1a19): undefined reference to `glShaderSource@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1a44): undefined reference to `glShaderSource@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1a4f): undefined reference to `glCompileShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1a6a): undefined reference to `glGetShaderiv@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1a94): undefined reference to `glCompileShader@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1aaf): undefined reference to `glGetShaderiv@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1adb): undefined reference to `glAttachShader@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1aea): undefined reference to `glAttachShader@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1b05): undefined reference to `glBindAttribLocation@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1b20): undefined reference to `glBindAttribLocation@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1b2b): undefined reference to `glLinkProgram@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1b46): undefined reference to `glGetProgramiv@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1bd9): undefined reference to `glGetUniformLocation@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1bf1): undefined reference to `glGetUniformLocation@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1c09): undefined reference to `glGetUniformLocation@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1c22): undefined reference to `glGenBuffers@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1c38): undefined reference to `_imp__glFinish@0'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d14): undefined reference to `_imp__glStencilFunc@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d5f): undefined reference to `glUseProgram@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d64): undefined reference to `_imp__glEnable@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d86): undefined reference to `_imp__glCullFace@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1d96): undefined reference to `_imp__glFrontFace@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1da7): undefined reference to `_imp__glDisable@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1dca): undefined reference to `_imp__glColorMask@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1df7): undefined reference to `_imp__glStencilMask@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1e0c): undefined reference to `_imp__glStencilOp@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1e4c): undefined reference to `_imp__glStencilFunc@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1e5b): undefined reference to `glActiveTexture@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1e60): undefined reference to `_imp__glBindTexture@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1edf): undefined reference to `glBindBuffer@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f07): undefined reference to `glBufferData@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f16): undefined reference to `glEnableVertexAttribArray@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f25): undefined reference to `glEnableVertexAttribArray@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f5c): undefined reference to `glVertexAttribPointer@24'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1f93): undefined reference to `glVertexAttribPointer@24'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1fa9): undefined reference to `glUniform1i@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1fc6): undefined reference to `glUniform4fv@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x1fce): undefined reference to `_imp__glDrawArrays@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2085): undefined reference to `glBlendFuncSeparate@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2141): undefined reference to `glStencilOpSeparate@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2168): undefined reference to `glStencilOpSeparate@16'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x217f): undefined reference to `_imp__glDrawArrays@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2289): undefined reference to `glDisableVertexAttribArray@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2298): undefined reference to `glDisableVertexAttribArray@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x22bd): undefined reference to `glBindBuffer@8'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x22cc): undefined reference to `glUseProgram@4'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2374): undefined reference to `_imp__glDrawArrays@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x249e): undefined reference to `_imp__glDrawArrays@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2532): undefined reference to `_imp__glDrawArrays@12'
libqnanopainter.a(qnanobackendgles2.cpp.o):qnanobackendgles2.cpp:(.text+0x2843): undefined reference to `_imp__glDrawArrays@12'

It seems something is off with ANGLE on Qt 5.12.x somehow. As a wild test, we substituted liblibGLESv2.a from 5.12 with the corresponding lib from 5.9 and compilation this time ended up correctly. But it obviously failed to start.

As said, it feels like something is off in Qt itself but maybe something can be missing or wrong in qnanopainter too? Any idea?

qnanopainter demos crash using Qt5.12's WebGL backend.

Qt5.12LTS has the ability to run apps on the browser: https://blog.qt.io/blog/2018/11/23/qt-quick-webgl-release-512/

Unfortunately, QNanoPainter-based apps crash under the new WebGL backend.

In order to debug qnanopainter examples under Qtcreator 4.8.0, with the new webgl backend:
(0) Load qnanopainter.pro in qtcreator
(1) Click "Projects" mode -> "Build & Run" -> "Your Desktop platform" -> Run
a) Under "run configuration" select "gallery" then click Add->"Clone Selected"
b) Name the cloned run configuration, for example, "gallery-webgl"
c) Under "Command line arguments" for run configuration "gallery-webgl" enter -platform webgl:port=8998
(2) Select run configuration "gallery-webgl" and click the "Start Debugging" button.
a) application will launch and wait for browser.
(3) in browser visit " http://localhost:8998 "
(4) The QtQuick component menus of app "gallery" will now be visible in the browser.
(5) Clicking any of the menus in the browser will crash the app once QNanoPainter is invoked. The other examples will crash immediately on startup (in the same code) as they init QNanoPainter right away.

The crash occurs at https://github.com/QUItCoding/qnanopainter/blob/master/libqnanopainter/qnanopainter.cpp#L157

Q_ASSERT_X(m_nvgContext, "QNanoPainter::QNanoPainter", "Could not init nanovg!");
Prior to the crash the following output is provided on stdout/stderr (note environment "QSG_RENDER_LOOP=threaded" and "QSG_INFO=1", running on Kubuntu 18.04LTS)

11:02:16: Debugging starts
QML debugging is enabled. Only use this in a safe environment.
QML Debugger: Waiting for connection on port 35553...
Running Qt >= 5.10, so enabling QML Shape example
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
libpng warning: iCCP: known incorrect sRGB profile
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
qt.scenegraph.general: texture atlas dimensions: 2048x1024
qt.scenegraph.general: R/G/B/A Buffers: -1 -1 -1 -1
qt.scenegraph.general: Depth Buffer: 24
qt.scenegraph.general: Stencil Buffer: 8
qt.scenegraph.general: Samples: -1
qt.scenegraph.general: GL_VENDOR: WebKit
qt.scenegraph.general: GL_RENDERER: WebKit WebGL
qt.scenegraph.general: GL_VERSION: WebGL 1.0 (OpenGL ES 2.0 Chromium)
qt.scenegraph.general: GL_EXTENSIONS: GL_OES_packed_depth_stencil GL_OES_element_index_uint GL_OES_depth_texture GL_OES_standard_derivatives
qt.scenegraph.general: Max Texture Size: 16384
qt.scenegraph.general: Debug context: false
Creating suitable QNanoBackend for OpenGL 2.0 context
Using backend: "OpenGL 2"
ASSERT failure in QNanoPainter::QNanoPainter: "Could not init nanovg!", file ../../../qnanopainter/libqnanopainter/qnanopainter.cpp, line 157
11:02:46: Debugging has finished

General Window error after delete a QNanoQuickItem

I am modifiying "painting" component on "gallery" example project in order to check the behaviour of the library when creating and deleting QNanoQuickItem.

I made a simple change on "painting/main.qml"(Attached the code):

  • No create PaintingItem by default, now it is a QML Component.
  • Add "Add Item" button: When click, a PaintingItem is created
  • Add "Delete Item" button: When click, the PaintingItem is destroyed.

I just start to play add and delete button and sometimes, after deleting the item, the UI is degraded (attached image).

Did you see this before? Is there something I can do for avoiding this?

Edit: just to add I am using QNANO_USE_RENDERNODE.

zip with code and image:
qnanopainter_issue.zip

Don't alter QT_NO_{DEBUG,WARNING,INFO}_OUTPUT in include.pri

It's great that you have a .pri file that enables easy embedding into other projects. But I think it's a bit hostile that this .pri alters "global" defines that may affect the rest of the project unexpectedly. In particular, QT_NO_{WARNING,DEBUG,INFO}_OUTPUT I think should not be changed by the .pri, but set by the including project.

The reason I am filing this is I had log output disabled for an entire library that I linked qnanopainter into, and it took me quite some time to track down the reason why I was no longer seeing useful logging output from my own code :)

Some questions about caching

I am writing a small free hand painting application. I have looked at the code for the free hand example, however I am unsure about the behavior of QNanoQuickItemPainter. When painting with QPainter what I do is the following:

  1. Use QPainter to draw on a buffer image
  2. Call update and schedule a redraw of the QQuickPaintedItem
  3. In my paint method, I draw the portions of the image I updated onto the item

Now, it seems that QNanoPainter does not allow to paint directly on other render targets (other than using Opengl), however I would like to know how can I replicate the above steps with QNanoPainter. From my testing, when the paint method of the painter is called, the entire item seems to be redrawn and the previous content is not really cached. So I have to redraw the entire scene again. However, this seems quite cost effective (right?). Here is some code from my app:

    void paint(QNanoPainter *painter) override{
        painter->scale(m_zoom);
        painter->setLineCap(QNanoPainter::LineCap::CAP_ROUND);
        painter->beginPath();

        // paint the points in the current stroke
        // m_currentStroke contains a QPolygonF
        auto pointsLength = m_currentStroke.length();

        // we need at least three points
        if(pointsLength > 2){
            for(int i = 0; i < pointsLength - 3; ++i){
                auto pressure0 = m_currentStroke.getFullPoint(i).second;
                auto pressure1 = m_currentStroke.getFullPoint(i+1).second;
                auto pressure2 = m_currentStroke.getFullPoint(i+2).second;

                auto averagePressure = (pressure0 + pressure1 + pressure2)/3;

                painter->setLineWidth(m_lineWidth * averagePressure);

                auto p0 = m_currentStroke.getFullPoint(i).first;
                auto p1 = m_currentStroke.getFullPoint(i+1).first;
                auto p2 = m_currentStroke.getFullPoint(i+2).first;

                // draw a quadratic curve for 3 points
                auto mid1 = (p0+p1)/2;
                auto mid2 = (p1+p2)/2;

                painter->moveTo(mid1);
                painter->quadTo(p1, mid2);
            }
            painter->stroke();
            m_drawnPoints = m_currentStroke.length();
            m_currentStroke.clear(); // if I do this the painter does not retain the previous state
        }
    }
    void synchronize(QNanoQuickItem *item) override{
        auto canvas = static_cast<Canvas*>(item);
        auto &currentStroke = canvas->m_currentStroke;

        // we only add the points that we have not painted already
        for(int i = m_drawnPoints; i < currentStroke.length(); ++i){
            auto p = currentStroke.points.at(i);
            auto pressure = currentStroke.pressures.at(i);
            m_currentStroke.addPoint(p,pressure);
        }
    }

Compiling on Windows

Hi,

I was trying to compile a project that uses qnanopainter on windows and it failed to compile as it couldn't find opengl functions. Is there any additional lib or dependency I must meet to compile this on windows?

Thanks!

How to render to an QOffscreenSurface?

I would like to render to an QOffscreenSurface, i.e. not rendering for a display but for an image file with much larger resolution. What needs to be changed to do so?

Any plans to migrate to CMake?

Since Qt6 is adopting CMake as its default build system, it would be nice if this library is migrated to CMake. Also I think it's best if nanovg is not included in the project and instead it should be listed as an external dependency.

Windows OpenGL Linking problem?

I'm trying to build the examples on Windows with Qt 5.9 and MSVC 2017.
Problem is that it fails at build time since it can't find lots of external symbols like glBindBuffer, glDeleteBuffers and lots of other OpenGL functions, this makes me think that is not linking to correct version of OpenGL.
I commented out DEFINES += QNANO_QT_GL_INCLUDE in include.pri so that OpenGl headers are included manually, since linker tries to include the system version and that's too old.

These are all the unresolved symbols:

qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glColorMask referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glCullFace referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glDeleteTextures referenced in function "int __cdecl glnvg__deleteTexture(struct GLNVGcontext *,int)" (?glnvg__deleteTexture@@YAHPEAUGLNVGcontext@@H@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glDisable referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glDrawArrays referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glEnable referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glFinish referenced in function "int __cdecl glnvg__renderCreate(void *)" (?glnvg__renderCreate@@YAHPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glFrontFace referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glGenTextures referenced in function "int __cdecl glnvg__renderCreateTexture(void *,int,int,int,int,unsigned char const *)" (?glnvg__renderCreateTexture@@YAHPEAXHHHHPEBE@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glGetError referenced in function "void __cdecl glnvg__checkError(struct GLNVGcontext *,char const *)" (?glnvg__checkError@@YAXPEAUGLNVGcontext@@PEBD@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glPixelStorei referenced in function "int __cdecl glnvg__renderCreateTexture(void *,int,int,int,int,unsigned char const *)" (?glnvg__renderCreateTexture@@YAHPEAXHHHHPEBE@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glStencilFunc referenced in function "void __cdecl glnvg__stencilFunc(struct GLNVGcontext *,unsigned int,int,unsigned int)" (?glnvg__stencilFunc@@YAXPEAUGLNVGcontext@@IHI@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glStencilMask referenced in function "void __cdecl glnvg__stencilMask(struct GLNVGcontext *,unsigned int)" (?glnvg__stencilMask@@YAXPEAUGLNVGcontext@@I@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glStencilOp referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glTexImage2D referenced in function "int __cdecl glnvg__renderCreateTexture(void *,int,int,int,int,unsigned char const *)" (?glnvg__renderCreateTexture@@YAHPEAXHHHHPEBE@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glTexParameteri referenced in function "int __cdecl glnvg__renderCreateTexture(void *,int,int,int,int,unsigned char const *)" (?glnvg__renderCreateTexture@@YAHPEAXHHHHPEBE@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol __imp_glTexSubImage2D referenced in function "int __cdecl glnvg__renderUpdateTexture(void *,int,int,int,int,int,unsigned char const *)" (?glnvg__renderUpdateTexture@@YAHPEAXHHHHHPEBE@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glActiveTexture referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glBlendFuncSeparate referenced in function "void __cdecl glnvg__blendFuncSeparate(struct GLNVGcontext *,struct GLNVGblend const *)" (?glnvg__blendFuncSeparate@@YAXPEAUGLNVGcontext@@PEBUGLNVGblend@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glBindBuffer referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glDeleteBuffers referenced in function "void __cdecl glnvg__renderDelete(void *)" (?glnvg__renderDelete@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGenBuffers referenced in function "int __cdecl glnvg__renderCreate(void *)" (?glnvg__renderCreate@@YAHPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glBufferData referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glStencilOpSeparate referenced in function "void __cdecl glnvg__fill(struct GLNVGcontext *,struct GLNVGcall *)" (?glnvg__fill@@YAXPEAUGLNVGcontext@@PEAUGLNVGcall@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glAttachShader referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glBindAttribLocation referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glCompileShader referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glCreateProgram referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glCreateShader referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glDeleteProgram referenced in function "void __cdecl glnvg__deleteShader(struct GLNVGshader *)" (?glnvg__deleteShader@@YAXPEAUGLNVGshader@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glDeleteShader referenced in function "void __cdecl glnvg__deleteShader(struct GLNVGshader *)" (?glnvg__deleteShader@@YAXPEAUGLNVGshader@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glDisableVertexAttribArray referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glEnableVertexAttribArray referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGetProgramiv referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGetProgramInfoLog referenced in function "void __cdecl glnvg__dumpProgramError(unsigned int,char const *)" (?glnvg__dumpProgramError@@YAXIPEBD@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGetShaderiv referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGetShaderInfoLog referenced in function "void __cdecl glnvg__dumpShaderError(unsigned int,char const *,char const *)" (?glnvg__dumpShaderError@@YAXIPEBD0@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glGetUniformLocation referenced in function "void __cdecl glnvg__getUniforms(struct GLNVGshader *)" (?glnvg__getUniforms@@YAXPEAUGLNVGshader@@@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glLinkProgram referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glShaderSource referenced in function "int __cdecl glnvg__createShader(struct GLNVGshader *,char const *,char const *,char const *,char const *,char const *)" (?glnvg__createShader@@YAHPEAUGLNVGshader@@PEBD1111@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glUseProgram referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glUniform1i referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glUniform4fv referenced in function "void __cdecl glnvg__setUniforms(struct GLNVGcontext *,int,int)" (?glnvg__setUniforms@@YAXPEAUGLNVGcontext@@HH@Z)
qnanopainter.obj : error LNK2019: unresolved external symbol glVertexAttribPointer referenced in function "void __cdecl glnvg__renderFlush(void *)" (?glnvg__renderFlush@@YAXPEAX@Z)```

Anyone else had this issue? Did you manage to solve it?

Crash on application exit

I'm getting a crash on application exit, on this line:

if (m_backend && m_nvgContext && QOpenGLContext::currentContext()) {

You guys are using a Q_GLOBAL_STATIC for the instance so destruction order is not really something we can control:

Q_GLOBAL_STATIC(QNanoPainter, instance)

Is it possible this is just QOpenGLContext::currentContext() being used after Qt has possibly already "deinitialized" itself?

This is a QtQuick application, using Qt 5.15.2.

Unrefreshed blank screen when embedded in StackView with QNANO_USE_RENDERNODE enabled

After enabling QNANO_USE_RENDERNODE in libqnanopainter/include.pri, a modified "HelloItem" example does not refresh the painted item, after the StackView is pop()'d. My modification is the qtcreator 4.11.0 template app "Qt Quick Application - Stack" with HelloItem as initialItem:

    StackView {
        id: stackView
        anchors.fill: parent
        initialItem:
            HelloItem {
            }
    }

When either of the stackView pages are pushed and then popped, the initial HelloItem is not refreshed and results in a blank screen. The application requires resizing to force a refresh.

Initially you see:
image

Selecting "page 1" gives:
image

Clicking the back arrow should display HelloItem but instead nothing displayed:
image

This problem seems related to #22

This is the source code of the example ( libqnanopainter/include.pri needs to be modified to enable QNANO_USE_RENDERNODE to reproduce the bug with this code):

helloitem.tar.gz

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.