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

QRawFont::pathForGlyph returns low quality glyph



  • I'm trying to render some text manually using QRawFont, but it looks like the path data it returns contains jagged lines instead of smooth curves

    Here's an example:
    Example

    The filled area is based on the QPainterPath returned by the QRawFont, the outline is rendered by a QGraphicsTextItem. both are based on the same QFont instance.
    It seems the jaggedness is more pronounced for smaller point sizes.

    is there any way to get the smooth shape of the glyph as a QPainterPath?



  • Maybe the issue is with some kind of numerical instability with QPainterPath?

    I managed to work around the issue by upscaling the QRawFont, getting the shape from that, simplifying it and scaling it back down:

    void upscaled_raw()
    {
        QFont font =  query;
        font.setPointSizeF(font.pointSizeF() * 1000);
        raw_scaled = QRawFont::fromFont(font);
    }
    
    QPainterPath path_for_glyph(quint32  glyph)
    {
        QPainterPath path = raw_scaled.pathForGlyph(glyph).simplified();
        if ( raw_scaled.pixelSize() == 0 )
            return path;
    
        QPainterPath dest;
        qreal mult = raw.pixelSize() / raw_scaled.pixelSize();
    
        std::array<QPointF, 3> data;
        int data_i = 0;
        for ( int i = 0; i < path.elementCount(); i++ )
        {
            auto element = path.elementAt(i);
            QPointF p = element * mult;
            switch ( element.type )
            {
                case QPainterPath::MoveToElement:
                    dest.moveTo(p);
                    break;
                case QPainterPath::LineToElement:
                    dest.lineTo(p);
                    break;
                case QPainterPath::CurveToElement:
                    data_i = 0;
                    data[0] = p;
                    break;
                case QPainterPath::CurveToDataElement:
                    ++data_i;
                    data[data_i] = p;
                    if ( data_i == 2 )
                    {
                        dest.cubicTo(data[0], data[1], data[2]);
                        data_i = -1;
                    }
                    break;
            }
        }
    
        return dest;
    }
    

    Note that both rescaling and simplifying are required to get a nice shape, neither works on its own.


Log in to reply