Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QQuickPaintedItem rotation causing aliasing



  • Hi,

    I'm working on implementing a custom round rectangle using QQuickPaintedItem so that I can change each corner radii independently and I'm running into an issue with rotating the object. Antialiasing seems to be working properly when the object is painted, but when I rotate the object via QML, aliasing appears along the diagonal edges of the rectangle. I can "hack" a fix to this by increasing the item's height and width and draw the rectangle inside the bounds of the item, but this solution requires a lot of hacky code.

    No rotation:
    0_1556128698190_3facc8f2-f09e-45d6-8877-0c64b44cf0c1-image.png

    Rotation with jaggies:
    0_1556128722708_7752b931-b8a9-4f07-9cc7-61919f2a64d7-image.png

    Here's my paint method:

        double buffer = 0; //Used to draw inside the item instead of on the edges
    
        if(tilt())
        {
            buffer += 1;
        }
        //start
        path.moveTo(width() - topRightRadius() - buffer, buffer);
    
        //Top horizontal
        path.lineTo(topLeftRadius() + buffer, buffer);
    
        //Top left radius
        path.arcTo(buffer, buffer, topLeftRadius(), topLeftRadius(), 90, 90);
    
        //Left vertical
        path.lineTo(buffer, height() - bottomLeftRadius() + buffer);
    
        //Bottom left radius
        path.arcTo(buffer, height() - bottomLeftRadius() - buffer, bottomLeftRadius(), bottomLeftRadius(), 180, 90);
    
        //Bottom horizontal
        path.lineTo(width() - bottomRightRadius() - buffer, height() - buffer);
    
        //Bottom right radius
        path.arcTo(width() - bottomRightRadius() - buffer, height() - bottomRightRadius() - buffer, bottomRightRadius(), bottomRightRadius(), 270, 90);
    
        //Right vertical
        path.lineTo(width() - buffer, topRightRadius() + buffer);
    
        //Top right radius
        path.arcTo(width() - topRightRadius() - buffer, buffer, topRightRadius(), topRightRadius(), 0, 90);
    
        setAntialiasing(true);
        QBrush brush(QColor("#53b748"));
    
        painter->setBrush(brush);
        painter->setPen(Qt::NoPen);
        painter->setRenderHint(QPainter::Antialiasing, true);
        painter->drawPath(path);
    

    Is there a fix for this? A better way to implement what I want? I'm open to any and all suggestions.


  • Moderators

    @zhannum
    how do you rotate via QML? are you sure is in exact 90 degree steps?

    A workaround could be to bind the antialiasing property to rotation % 90.0 !== 0.0



  • @raven-worx

    I only want to rotate 5 degrees. I want to rotate when the item is dragged, so I have:

    rotation: Drag.active ? 5 : 0
    

  • Moderators

    @zhannum
    also make sure that you round the x and y coordinates after the drag has finished.
    Ensuring that the pos and size is even on pixels should prevent the need for antialiasing



  • @raven-worx
    I'm not sure what you mean. Even if I just rotate it in place without dragging it the aliasing still appears:
    0_1556132002084_652b52f8-5f7a-4d80-be4e-aaffdd998863-image.png

    rotation: 5
    

  • Moderators

    @zhannum said in QQuickPaintedItem rotation causing aliasing:

    I'm not sure what you mean.

    i meant when you are finished with dragging, you should ensure that the item's x and y coordinate and its width and height is not any floating value

    Even if I just rotate it in place without dragging it the aliasing still appears

    this doesnt look very antialiased to me?
    your first screenshot does though.



  • @raven-worx

    The x and y of the object after a drop event are set in QML, and are always set to integer values.

    this doesnt look very antialiased to me?
    your first screenshot does though.

    I agree. The jagged aliasing is what I'd like to fix. Basically how the diagonal line is made up of small horizontal lines, giving the appearance of steps.
    0_1556136852368_c495ce12-1a2b-4115-aa66-85d5678e9af1-image.png

    With my hacky fix I've implemented, this is what the result looks like, which is what I want:
    0_1556136996928_b9ea979e-d001-4edb-93ab-d259cf8a4e02-image.png

    To better illustrate how I'm "hacking" a solution, i've set the fillColor of the item to white:
    0_1556137075921_13551cd9-3b41-4bfb-9826-fbe72dcf40a0-image.png

    You can see that the edges of the QQuickItem become jagged when rotated.


  • Moderators

    @zhannum said in QQuickPaintedItem rotation causing aliasing:

    I agree. The jagged aliasing is what I'd like to fix

    now i finally got you.
    You may want to read the following. If you use OpenGL?
    https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html#antialiasing

    so you might want to try msaa. I assume the software renderer's (QPainter) antialiasing method is closer to to this one.


Log in to reply