PDA

View Full Version : QPainter::drawText and floating point precision



kssm
15th December 2013, 21:33
Hi!

I want to draw text with floating point precision,
but so far I have not succeeded.

QPainter::drawText takes a QPointF as first
argument, but it seems like it could
just as well just have taken a QPoint as argument instead.

I've tried to set the SmoothPixmapTransform, Antialiasing,
and HighQualityAntialiasing rendering hints, but none of them
seems to make a difference.

I'm using Qt 4.8.

Is floating point precision supported in Qt 4.8? (Am I
just doing something wrong?)

And in case not, will it help to use Qt 5 instead?

Thanks for any help and clarification about what Qt does.
If Qt doesn't support floating point precision when drawing
text, I'll just have to do it manually instead, but I rather not.

-K

Added after 4 minutes:

I should also add that I'm painting to a QImage.

I've also tried to explicitly tell Qt to use the
raster engine, but it makes no difference.

I'm developing on Linux, but the program
runs on OSX and Windows as well.

Lykurg
16th December 2013, 08:57
Have you tried to use QPainter::TextAntialiasing?

kssm
16th December 2013, 10:23
Have you tried to use QPainter::TextAntialiasing?

Yes, but since TextAntialiasing is ON by default, I didn't wrote that I had tried that, because then someone
would comment that TextAntialising is ON by default. :p

Added after 1 6 minutes:

I've dived into the Qt source, and as far as I see, QPainter::drawPath is the
drawing primitive used to draw text on QImages on Raster, and that method should
provide floating point precision.

Unless anyone comes up with a bright idea, I'll just compile Qt myself, and insert
some debug printings here and there to see what's happening.

Lykurg
16th December 2013, 14:01
Yes, but since TextAntialiasing is ON by default, I didn't wrote that I had tried that, because then someone
would comment that TextAntialising is ON by default. :p
:D Ups, I was not aware that it is turned ON by default.

kssm
16th December 2013, 14:12
I found a solution. Glyphs painting are cached, but it seems like the keys used for caching
are in integer format, (or that the cached glyphs are stored in integer format).

If I comment out line 3195 (or thereabout) in qpaintengine_raster.cpp, which looks like this:
"if (!drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), fontEngine))"

drawText works properly.

Is there some other way to turn off caching, besides commenting out that line?

Or perhaps this should be considered a bug? I guess some programs would run slower
if the glyph caching used floats for key formats, although float keys would be correct.

At least I haven't seen this limitation documented anywhere, and that should be considered
a bug.

kssm
16th December 2013, 17:33
Using painter.translate() doesn't help either.

I guess we are supposed to draw text using drawGlyphRun in these situations?
I hope that works, if not I might have to use a patched version of Qt for the program.

Using painter.translate() doesn't help either.

I guess we are supposed to draw text using drawGlyphRun in these situations?
I hope that works, if not I might have to use a patched version of Qt for the program.

Using painter.translate() doesn't help either.

I guess we are supposed to draw text using drawGlyphRun in these situations?
I hope that works, if not I might have to use a patched version of Qt for the program.

Using painter.translate() doesn't help either.

I guess we are supposed to draw text using drawGlyphRun in these situations?
I hope that works, if not I might have to use a patched version of Qt for the program.

Added after 19 minutes:

Nope, drawGlyphRun doesn't work either:



static void myDrawText(QPainter *painter, QPointF p, QString text){
QTextLayout textLayout(text, painter->font(), painter->device());

//int leading = fontMetrics.leading();
qreal height = 0;
textLayout.beginLayout();
while (1) {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;

line.setLineWidth(50.0f);//lineWidth);
height += 5.4; //leading;
line.setPosition(QPointF(0, height));
height += line.height();
}
textLayout.endLayout();


//textLayout.draw(painter, p);

QList<QGlyphRun> glyphs = textLayout.glyphRuns();

QList<QGlyphRun>::iterator i;
for (i = glyphs.begin(); i != glyphs.end(); ++i) {
printf("Drawing something\n");
QGlyphRun glyph = *i;
//glyph.setRawFont(QRawFont::fromFont(painter->font()));
painter->drawGlyphRun(p, (const QGlyphRun &)glyph);
}
}


Guess I'll just rip out some code from the Qt source and insert it into my program.
(they're both GPL)

Added after 43 minutes:

Got it. This works:



void myDrawText(QPainter *painter, QPointF p, QString text){

QRawFont rawFont = QRawFont::fromFont(painter->font());
QVector<quint32> indexes = rawFont.glyphIndexesForString(text);

painter->save();
printf("num indexes: %d\n",indexes.count());
for(unsigned int i=0; i<indexes.count(); i++){
QPainterPath path = rawFont.pathForGlyph(indexes[i]);
painter->translate(QPointF(p.x(), p.y() + i*0));
painter->fillPath(path,painter->pen().brush());
}
painter->restore();
}