Get remaining part of a large string to fit fixed rectangle



  • I have a very large string, a font and a rectangle to draw that string into. If the string doesn't fit, I would like to know the size of string that does fit into that rectangle... if the string does fit, then I would like to know bounding rectangle height. How to achieve this?


  • Qt Champions 2016

    hi have you read about
    http://doc.qt.io/qt-5.5/qpainter.html#drawText-5
    It can return a rectangle for the complete text.



  • @mrjj Yes, I have seen that. Unfortunately, it doesn't help in getting length of string that fits.


  • Qt Champions 2016

    @Borzh
    So say we have
    abcdefg and we can only display abc
    you want to know the sub string that was possible to draw
    given the rect?

    hmm, it reports back in pixels not letters.
    Sorry Im not aware of anything that would report back such info.



  • @mrjj Yes, that is correct. Of course, I could create a method that acts like a binary search, halfing/doubling string length calling boundingRect(), until low margin == high margin, but I assume this is not very optimized.


  • Qt Champions 2016

    @Borzh
    well, you could also do the word wrap yourself, using
    http://doc.qt.io/qt-5.5/qfontmetrics.html#details
    or look at source code for drawtext and see if you reuse some of it for a version
    that can return the substring.

    Is this big string with spaces ?



  • I am posting my own binary search algorithm. BTW you can use QFontMetrics instead of QPainter if you want.

    int FontUtils::FittingLength(const QString& s, QPainter &p, const QRectF& rect,
                                 int flags/* = Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap*/)
    {
        QRectF r = p.boundingRect(rect, flags, s);
        if (r.height() <= rect.height()) // String fits rect.
            return s.length();
    
        // Apply binary search.
        QString sub;
        int left = 0, right = s.length()-1;
        do
        {
            int pivot = (left + right)>>1; // Middle point.
            sub = s.mid(0, pivot+1);
            r = p.boundingRect(rect, flags, sub);
    
            if (r.height() > rect.height()) // Doesn't fit.
                right = pivot-1;
            else
                left = pivot+1;
        } while (left < right);
    
        left++; // Length of string is one char more.
    
        // Remove trailing word if it doesn't fit.
        if  ( !s.at(left).isSpace() && !s.at(left+1).isSpace() )
        {
            while ( (--left > 0) && !sub.at(left).isSpace() );
            left++;
        }
    
        return left;
    }

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.