How to calcuate font size to fit a text inside a given rectangle
-
wrote on 10 Jun 2013, 10:31 last edited by
Dear all,
I want to display a text fitting all inside the screen of a mobile device.
So, I'm trying to find out an efficient way to calculate the correct font size in order to display the text all inside the screen size.Any suggestions ??
Thanks,
Gianluca. -
wrote on 10 Jun 2013, 11:05 last edited by
Hi Gianluca.
Did you try with "QFontMetrics":http://qt-project.org/doc/qt-4.8/qfontmetrics.html ?
From doc:
"The QFontMetrics class provides font metrics information.
QFontMetrics functions calculate the size of characters and strings for a given font.
..."
Regards. -
wrote on 10 Jun 2013, 11:43 last edited by
I played a bit with QFontMetrics... but if the text is a rich text it continue to work??
I'm bit confused by the documentation of QFontMetrics::boundingRect:"Newline characters are processed as normal characters, not as linebreaks."
So, it seems that it returns the boundingRect as if the text is written on a long single line.
And it say nothing about right text :-(
Thanks,
Gianluca. -
wrote on 3 Oct 2013, 20:09 last edited by
I'm in the same boat. I'm given a rectangle size, and I want to grow my font to fit within a rectangle. I think QFontMetrics allows you to calculate a rectangle with a string, not a font size based off of a rectangle.
-
if you want to do checks with rich text you will need to do this with QTextDocument instead. You can use the following methods for this:
QTextDocument::setHtml()
QTextDocument::setPageSize();
QTextDocument::setDefaultFont()
QTextDocument::::documentLayout()->documentSize() -
wrote on 4 Oct 2013, 12:25 last edited by
But the question is the opposite.
I want to know what should be the font size in order to fit inside a given rectangle.
With the documentSize() method only, for get the answer of the above question I should iterate over all possible font size starting from 1 until I get the value corresponding to the nearest documentSize() to the given rectangle.
But this procedure it's very heavy and the computational cost is not acceptable. -
exactly... AFAIK there is no function which provides it the other way around.
What are the estimated bounds of the font size in your case?
5pt - 30pt ... meaning 25 iterations in worst case. What system you developing for? Embedded? -
wrote on 4 Oct 2013, 12:56 last edited by
I'm developing for mobile platforms.
I would like to get a way to estimate the font size to drastically reduce the number of iterations. Because 20 iterations on setting font on a QTextDocument and ask the documentSize() it seems too much for me.
It's too much because I need to do the calculation during the dynamical changing of the screen dimension due to rotations or to the appear of keyboard. And in that situations if my code spend more than few milliseconds to calculate the new fontsize the animation will be crap.
Using a QTextDocument, I cannot do more that 5 iterations.Also, calculating the bounds for the font size it's not too easy if I don't know the answer to my question. Because, there are many different phones and tablets with so many different screen dimension and density of pixel that It's unreasonable to use a bounds that works for all mobile devices.
Instead, if I can figure out a way to estimate the font size for a given rectangle, I can use the routine to calculate the bounds of the font on the basis of the maximum dimension for the rectangle depending on the screen resolution of the mobile device. -
have you tested it ... i mean performance wise?
I would assume you could easily load 50 iterations at least without noticing (depending on the device ofc). -
wrote on 4 Oct 2013, 13:52 last edited by
Yes, I tested... only visually not with precise timing.
And, If the program do more than 5 iterations the rotation animation (from landscape to portrait and viceversa) will stop about in the middle and then restart.
I suppose that the delay of iterations in the code that block the GUI thread, blocks also the animations.
(On a very cheap mobile phone). -
wrote on 4 Oct 2013, 15:33 last edited by
Maybe I am not understanding, but can't you just use the initial rich-text result as a scale?
If you take your initial estimated font size (f) and your resulting rich-text rect (r) and your size constraint (c) you should be able to get it in one try with a formula like this:
int meanSize = r.width * r.height;
int meanCanvas = c.width * c.height;
int newPixelSize = floor( f * (meanCanvas / meanSize) );So for example my test text renders to 200 x 335 inside a 210x210 space at 24px font:
meanSize = 67000
meanCanvas = 44100
newPixelSize = 15.797 => 15It works in my tests:
[code]Mean volume: 50576
Canvas volume: 29736
Scale 12 to 7
Mean volume: 50184
Canvas volume: 34846
Scale 12 to 8
Mean volume: 48928
Canvas volume: 47978
Scale 12 to 11
Mean volume: 51800
Canvas volume: 71154
Scale 12 to 16
Mean volume: 52680
Canvas volume: 120053
Scale 12 to 27
Mean volume: 54000
Canvas volume: 128028
Scale 12 to 28 [/code]Here's the relevant method. It's a basic QMainWindow object with a QTextBrowser as the central widget called 'textBrowser':
[code]void MainWindow::resizeEvent(QResizeEvent *e)
{
QSizeF meanSize = ui->textBrowser->document()->size();
int meanVolume = meanSize.width() * meanSize.height();
qDebug() << "Mean volume:" << meanVolume;
if( meanVolume <= 0 )
return;int canvasVolume = ui->textBrowser->width() * ui->textBrowser->height(); qDebug() << "Canvas volume:" << canvasVolume; if( canvasVolume <= 0 ) return; int pixelSize = ui->textBrowser->fontInfo().pixelSize(); int newPixelSize = qFloor( (double)pixelSize * ( (double)canvasVolume / (double)meanVolume ) ); qDebug() << "Scale" << pixelSize << "to" << newPixelSize; QMainWindow::resizeEvent(e);
}[/code]
-
wrote on 4 Oct 2013, 21:26 last edited by
Nice.
I have the same question for a QSplashScreen...
Because splash->showMessage( richText ) enables you to set some styled and translated document, is seems impossible to know its original size, and tweak the font as you proposed.
Any clue ?
-
wrote on 25 Jul 2016, 07:45 last edited by SebastienL
Here is my code the fit (in heigth) a text, works quite well (error < 2% I guess) :
void scalePainterFontSizeToFit(QPainter &painter, QFont &r_font, float _heightToFitIn) { float oldFontSize, newFontSize, oldHeight; // Init oldFontSize=r_font.pointSizeF(); // Loop for (int i=0 ; i<3 ; i++) { oldHeight = painter.fontMetrics().boundingRect('D').height(); newFontSize = (_heightToFitIn / oldHeight) * oldFontSize; r_font.setPointSizeF(newFontSize); painter.setFont(r_font); oldFontSize = newFontSize; //qDebug() << "OldFontSize=" << oldFontSize << "HtoFitIn=" << _heightToFitIn << " fontHeight=" << oldHeight << " newFontSize=" << newFontSize; } // End r_font.setPointSizeF(newFontSize); painter.setFont(r_font); }